diff --git a/cgo/cgo.go b/cgo/cgo.go index d5f1221200..4a5d7efedf 100644 --- a/cgo/cgo.go +++ b/cgo/cgo.go @@ -162,6 +162,13 @@ func __GoBytes(unsafe.Pointer, uintptr) []byte func GoBytes(ptr unsafe.Pointer, length C.int) []byte { return C.__GoBytes(ptr, uintptr(length)) } + +//go:linkname C.__CBytes runtime.cgo_CBytes +func __CBytes([]byte) unsafe.Pointer + +func CBytes(b []byte) unsafe.Pointer { + return C.__CBytes(b) +} ` // Process extracts `import "C"` statements from the AST, parses the comment @@ -218,7 +225,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl switch decl := decl.(type) { case *ast.FuncDecl: switch decl.Name.Name { - case "CString", "GoString", "GoStringN", "__GoStringN", "GoBytes", "__GoBytes": + case "CString", "GoString", "GoStringN", "__GoStringN", "GoBytes", "__GoBytes", "CBytes", "__CBytes": // Adjust the name to have a "C." prefix so it is correctly // resolved. decl.Name.Name = "C." + decl.Name.Name diff --git a/cgo/testdata/basic.out.go b/cgo/testdata/basic.out.go index f2daa78dac..6c2623980e 100644 --- a/cgo/testdata/basic.out.go +++ b/cgo/testdata/basic.out.go @@ -24,6 +24,13 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { return C.__GoBytes(ptr, uintptr(length)) } +//go:linkname C.__CBytes runtime.cgo_CBytes +func C.__CBytes([]byte) unsafe.Pointer + +func C.CBytes(b []byte) unsafe.Pointer { + return C.__CBytes(b) +} + type ( C.char uint8 C.schar int8 diff --git a/cgo/testdata/const.out.go b/cgo/testdata/const.out.go index 4a5f5fd5b0..2b48163b4b 100644 --- a/cgo/testdata/const.out.go +++ b/cgo/testdata/const.out.go @@ -24,6 +24,13 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { return C.__GoBytes(ptr, uintptr(length)) } +//go:linkname C.__CBytes runtime.cgo_CBytes +func C.__CBytes([]byte) unsafe.Pointer + +func C.CBytes(b []byte) unsafe.Pointer { + return C.__CBytes(b) +} + type ( C.char uint8 C.schar int8 diff --git a/cgo/testdata/errors.out.go b/cgo/testdata/errors.out.go index d0e04320ae..43a6a65c97 100644 --- a/cgo/testdata/errors.out.go +++ b/cgo/testdata/errors.out.go @@ -44,6 +44,13 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { return C.__GoBytes(ptr, uintptr(length)) } +//go:linkname C.__CBytes runtime.cgo_CBytes +func C.__CBytes([]byte) unsafe.Pointer + +func C.CBytes(b []byte) unsafe.Pointer { + return C.__CBytes(b) +} + type ( C.char uint8 C.schar int8 diff --git a/cgo/testdata/flags.out.go b/cgo/testdata/flags.out.go index 72520ab6d9..83ca604200 100644 --- a/cgo/testdata/flags.out.go +++ b/cgo/testdata/flags.out.go @@ -29,6 +29,13 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { return C.__GoBytes(ptr, uintptr(length)) } +//go:linkname C.__CBytes runtime.cgo_CBytes +func C.__CBytes([]byte) unsafe.Pointer + +func C.CBytes(b []byte) unsafe.Pointer { + return C.__CBytes(b) +} + type ( C.char uint8 C.schar int8 diff --git a/cgo/testdata/symbols.out.go b/cgo/testdata/symbols.out.go index f2826ae2e9..569cb65f6a 100644 --- a/cgo/testdata/symbols.out.go +++ b/cgo/testdata/symbols.out.go @@ -24,6 +24,13 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { return C.__GoBytes(ptr, uintptr(length)) } +//go:linkname C.__CBytes runtime.cgo_CBytes +func C.__CBytes([]byte) unsafe.Pointer + +func C.CBytes(b []byte) unsafe.Pointer { + return C.__CBytes(b) +} + type ( C.char uint8 C.schar int8 diff --git a/cgo/testdata/types.out.go b/cgo/testdata/types.out.go index a35d3733c4..e5382ec803 100644 --- a/cgo/testdata/types.out.go +++ b/cgo/testdata/types.out.go @@ -24,6 +24,13 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { return C.__GoBytes(ptr, uintptr(length)) } +//go:linkname C.__CBytes runtime.cgo_CBytes +func C.__CBytes([]byte) unsafe.Pointer + +func C.CBytes(b []byte) unsafe.Pointer { + return C.__CBytes(b) +} + type ( C.char uint8 C.schar int8 diff --git a/src/runtime/string.go b/src/runtime/string.go index 13bfcd0ed2..aeefe1d4fa 100644 --- a/src/runtime/string.go +++ b/src/runtime/string.go @@ -283,3 +283,10 @@ func cgo_GoBytes(ptr unsafe.Pointer, length uintptr) []byte { } return buf } + +func cgo_CBytes(b []byte) unsafe.Pointer { + p := malloc(uintptr(len(b))) + s := unsafe.Slice((*byte)(p), len(b)) + copy(s, b) + return p +} diff --git a/testdata/cgo/main.go b/testdata/cgo/main.go index ddd1992e22..00e0ba01da 100644 --- a/testdata/cgo/main.go +++ b/testdata/cgo/main.go @@ -165,6 +165,8 @@ func main() { println("C.GoString(nil):", C.GoString(nil)) println("len(C.GoStringN(nil, 0)):", len(C.GoStringN(nil, 0))) println("len(C.GoBytes(nil, 0)):", len(C.GoBytes(nil, 0))) + println("len(C.GoBytes(C.CBytes(nil),0)):", len(C.GoBytes(C.CBytes(nil), 0))) + println(`rountrip CBytes:`, C.GoString((*C.char)(C.CBytes([]byte("hello\000"))))) // libc: test whether C functions work at all. buf1 := []byte("foobar\x00") diff --git a/testdata/cgo/out.txt b/testdata/cgo/out.txt index 4ea45d864c..3088d4cb4d 100644 --- a/testdata/cgo/out.txt +++ b/testdata/cgo/out.txt @@ -73,6 +73,8 @@ C.CStringN: 4 2 0 4 8 C.GoString(nil): len(C.GoStringN(nil, 0)): 0 len(C.GoBytes(nil, 0)): 0 +len(C.GoBytes(C.CBytes(nil),0)): 0 +rountrip CBytes: hello copied string: foobar CGo sqrt(3): +1.732051e+000 C sqrt(3): +1.732051e+000