diff options
author | Ayke van Laethem <[email protected]> | 2021-11-11 16:11:08 +0100 |
---|---|---|
committer | Ron Evans <[email protected]> | 2021-11-24 21:09:29 +0100 |
commit | c31aef06ba131051cba4a18f336eb7d820faa4e7 (patch) | |
tree | 219fe13aa3b09f331195686d664b58d0b64a52b8 /cgo | |
parent | 6bd18af5ef02eddb8507cdbe40ffbe8d594af910 (diff) | |
download | tinygo-c31aef06ba131051cba4a18f336eb7d820faa4e7.tar.gz tinygo-c31aef06ba131051cba4a18f336eb7d820faa4e7.zip |
cgo: add support for C.CString and related functions
Diffstat (limited to 'cgo')
-rw-r--r-- | cgo/cgo.go | 42 | ||||
-rw-r--r-- | cgo/testdata/basic.out.go | 20 | ||||
-rw-r--r-- | cgo/testdata/const.out.go | 20 | ||||
-rw-r--r-- | cgo/testdata/errors.out.go | 20 | ||||
-rw-r--r-- | cgo/testdata/flags.out.go | 20 | ||||
-rw-r--r-- | cgo/testdata/symbols.out.go | 20 | ||||
-rw-r--r-- | cgo/testdata/types.out.go | 20 |
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 |