aboutsummaryrefslogtreecommitdiffhomepage
path: root/cgo
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2021-11-11 16:11:08 +0100
committerRon Evans <[email protected]>2021-11-24 21:09:29 +0100
commitc31aef06ba131051cba4a18f336eb7d820faa4e7 (patch)
tree219fe13aa3b09f331195686d664b58d0b64a52b8 /cgo
parent6bd18af5ef02eddb8507cdbe40ffbe8d594af910 (diff)
downloadtinygo-c31aef06ba131051cba4a18f336eb7d820faa4e7.tar.gz
tinygo-c31aef06ba131051cba4a18f336eb7d820faa4e7.zip
cgo: add support for C.CString and related functions
Diffstat (limited to 'cgo')
-rw-r--r--cgo/cgo.go42
-rw-r--r--cgo/testdata/basic.out.go20
-rw-r--r--cgo/testdata/const.out.go20
-rw-r--r--cgo/testdata/errors.out.go20
-rw-r--r--cgo/testdata/flags.out.go20
-rw-r--r--cgo/testdata/symbols.out.go20
-rw-r--r--cgo/testdata/types.out.go20
7 files changed, 162 insertions, 0 deletions
diff --git a/cgo/cgo.go b/cgo/cgo.go
index 81c4a17d2..cd0c29d8f 100644
--- a/cgo/cgo.go
+++ b/cgo/cgo.go
@@ -165,10 +165,35 @@ typedef unsigned long long _Cgo_ulonglong;
// First part of the generated Go file. Written here as Go because that's much
// easier than constructing the entire AST in memory.
+// The string/bytes functions below implement C.CString etc. To make sure the
+// runtime doesn't need to know the C int type, lengths are converted to uintptr
+// first.
+// These functions will be modified to get a "C." prefix, so the source below
+// doesn't reflect the final AST.
const generatedGoFilePrefix = `
import "unsafe"
var _ unsafe.Pointer
+
+//go:linkname C.CString runtime.cgo_CString
+func CString(string) *C.char
+
+//go:linkname C.GoString runtime.cgo_GoString
+func GoString(*C.char) string
+
+//go:linkname C.__GoStringN runtime.cgo_GoStringN
+func __GoStringN(*C.char, uintptr) string
+
+func GoStringN(cstr *C.char, length C.int) string {
+ return C.__GoStringN(cstr, uintptr(length))
+}
+
+//go:linkname C.__GoBytes runtime.cgo_GoBytes
+func __GoBytes(unsafe.Pointer, uintptr) []byte
+
+func GoBytes(ptr unsafe.Pointer, length C.int) []byte {
+ return C.__GoBytes(ptr, uintptr(length))
+}
`
// Process extracts `import "C"` statements from the AST, parses the comment
@@ -219,6 +244,23 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
// This is always a bug in the cgo package.
panic("unexpected error: " + err.Error())
}
+ // If the Comments field is not set to nil, the fmt package will get
+ // confused about where comments should go.
+ p.generated.Comments = nil
+ // Adjust some of the functions in there.
+ for _, decl := range p.generated.Decls {
+ switch decl := decl.(type) {
+ case *ast.FuncDecl:
+ switch decl.Name.Name {
+ case "CString", "GoString", "GoStringN", "__GoStringN", "GoBytes", "__GoBytes":
+ // Adjust the name to have a "C." prefix so it is correctly
+ // resolved.
+ decl.Name.Name = "C." + decl.Name.Name
+ }
+ }
+ }
+ // Patch some types, for example *C.char in C.CString.
+ astutil.Apply(p.generated, p.walker, nil)
// Find all C.* symbols.
for _, f := range files {
diff --git a/cgo/testdata/basic.out.go b/cgo/testdata/basic.out.go
index 1fb2c4d1a..125605de8 100644
--- a/cgo/testdata/basic.out.go
+++ b/cgo/testdata/basic.out.go
@@ -4,6 +4,26 @@ import "unsafe"
var _ unsafe.Pointer
+//go:linkname C.CString runtime.cgo_CString
+func C.CString(string) *C.char
+
+//go:linkname C.GoString runtime.cgo_GoString
+func C.GoString(*C.char) string
+
+//go:linkname C.__GoStringN runtime.cgo_GoStringN
+func C.__GoStringN(*C.char, uintptr) string
+
+func C.GoStringN(cstr *C.char, length C.int) string {
+ return C.__GoStringN(cstr, uintptr(length))
+}
+
+//go:linkname C.__GoBytes runtime.cgo_GoBytes
+func C.__GoBytes(unsafe.Pointer, uintptr) []byte
+
+func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
+ return C.__GoBytes(ptr, uintptr(length))
+}
+
type C.int16_t = int16
type C.int32_t = int32
type C.int64_t = int64
diff --git a/cgo/testdata/const.out.go b/cgo/testdata/const.out.go
index d213a6723..e12cded4f 100644
--- a/cgo/testdata/const.out.go
+++ b/cgo/testdata/const.out.go
@@ -4,6 +4,26 @@ import "unsafe"
var _ unsafe.Pointer
+//go:linkname C.CString runtime.cgo_CString
+func C.CString(string) *C.char
+
+//go:linkname C.GoString runtime.cgo_GoString
+func C.GoString(*C.char) string
+
+//go:linkname C.__GoStringN runtime.cgo_GoStringN
+func C.__GoStringN(*C.char, uintptr) string
+
+func C.GoStringN(cstr *C.char, length C.int) string {
+ return C.__GoStringN(cstr, uintptr(length))
+}
+
+//go:linkname C.__GoBytes runtime.cgo_GoBytes
+func C.__GoBytes(unsafe.Pointer, uintptr) []byte
+
+func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
+ return C.__GoBytes(ptr, uintptr(length))
+}
+
const C.bar = C.foo
const C.foo = 3
diff --git a/cgo/testdata/errors.out.go b/cgo/testdata/errors.out.go
index 212b37ed0..8200a459f 100644
--- a/cgo/testdata/errors.out.go
+++ b/cgo/testdata/errors.out.go
@@ -18,6 +18,26 @@ import "unsafe"
var _ unsafe.Pointer
+//go:linkname C.CString runtime.cgo_CString
+func C.CString(string) *C.char
+
+//go:linkname C.GoString runtime.cgo_GoString
+func C.GoString(*C.char) string
+
+//go:linkname C.__GoStringN runtime.cgo_GoStringN
+func C.__GoStringN(*C.char, uintptr) string
+
+func C.GoStringN(cstr *C.char, length C.int) string {
+ return C.__GoStringN(cstr, uintptr(length))
+}
+
+//go:linkname C.__GoBytes runtime.cgo_GoBytes
+func C.__GoBytes(unsafe.Pointer, uintptr) []byte
+
+func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
+ return C.__GoBytes(ptr, uintptr(length))
+}
+
const C.SOME_CONST_3 = 1234
type C.int16_t = int16
diff --git a/cgo/testdata/flags.out.go b/cgo/testdata/flags.out.go
index 4eb70112a..920778655 100644
--- a/cgo/testdata/flags.out.go
+++ b/cgo/testdata/flags.out.go
@@ -9,6 +9,26 @@ import "unsafe"
var _ unsafe.Pointer
+//go:linkname C.CString runtime.cgo_CString
+func C.CString(string) *C.char
+
+//go:linkname C.GoString runtime.cgo_GoString
+func C.GoString(*C.char) string
+
+//go:linkname C.__GoStringN runtime.cgo_GoStringN
+func C.__GoStringN(*C.char, uintptr) string
+
+func C.GoStringN(cstr *C.char, length C.int) string {
+ return C.__GoStringN(cstr, uintptr(length))
+}
+
+//go:linkname C.__GoBytes runtime.cgo_GoBytes
+func C.__GoBytes(unsafe.Pointer, uintptr) []byte
+
+func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
+ return C.__GoBytes(ptr, uintptr(length))
+}
+
const C.BAR = 3
const C.FOO_H = 1
diff --git a/cgo/testdata/symbols.out.go b/cgo/testdata/symbols.out.go
index 97a9522b7..53ec4f0b0 100644
--- a/cgo/testdata/symbols.out.go
+++ b/cgo/testdata/symbols.out.go
@@ -4,6 +4,26 @@ import "unsafe"
var _ unsafe.Pointer
+//go:linkname C.CString runtime.cgo_CString
+func C.CString(string) *C.char
+
+//go:linkname C.GoString runtime.cgo_GoString
+func C.GoString(*C.char) string
+
+//go:linkname C.__GoStringN runtime.cgo_GoStringN
+func C.__GoStringN(*C.char, uintptr) string
+
+func C.GoStringN(cstr *C.char, length C.int) string {
+ return C.__GoStringN(cstr, uintptr(length))
+}
+
+//go:linkname C.__GoBytes runtime.cgo_GoBytes
+func C.__GoBytes(unsafe.Pointer, uintptr) []byte
+
+func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
+ return C.__GoBytes(ptr, uintptr(length))
+}
+
//export foo
func C.foo(a C.int, b C.int) C.int
diff --git a/cgo/testdata/types.out.go b/cgo/testdata/types.out.go
index 1864e33f5..639d1f4f3 100644
--- a/cgo/testdata/types.out.go
+++ b/cgo/testdata/types.out.go
@@ -4,6 +4,26 @@ import "unsafe"
var _ unsafe.Pointer
+//go:linkname C.CString runtime.cgo_CString
+func C.CString(string) *C.char
+
+//go:linkname C.GoString runtime.cgo_GoString
+func C.GoString(*C.char) string
+
+//go:linkname C.__GoStringN runtime.cgo_GoStringN
+func C.__GoStringN(*C.char, uintptr) string
+
+func C.GoStringN(cstr *C.char, length C.int) string {
+ return C.__GoStringN(cstr, uintptr(length))
+}
+
+//go:linkname C.__GoBytes runtime.cgo_GoBytes
+func C.__GoBytes(unsafe.Pointer, uintptr) []byte
+
+func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
+ return C.__GoBytes(ptr, uintptr(length))
+}
+
const C.option2A = 20
const C.optionA = 0
const C.optionB = 1