]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: add C.CBytes
authorJames Bardin <j.bardin@gmail.com>
Wed, 16 Mar 2016 17:53:53 +0000 (13:53 -0400)
committerIan Lance Taylor <iant@golang.org>
Wed, 16 Mar 2016 23:22:10 +0000 (23:22 +0000)
Add a C.CBytes function to copy a Go byte slice into C memory. This
returns an unsafe.Pointer, since that is what needs to be passed to
C.free, and the data is often opaque bytes anyway.

Fixes #14838

Change-Id: Ic7bc29637eb6f1f5ee409b3898c702a59833a85a
Reviewed-on: https://go-review.googlesource.com/20762
Reviewed-by: Ian Lance Taylor <iant@golang.org>
misc/cgo/test/cgo_test.go
misc/cgo/test/issue14838.go [new file with mode: 0644]
src/cmd/cgo/doc.go
src/cmd/cgo/out.go

index 48fb6f18b7fb537144b10c174a02eadd74ca6e3e..9f493e6cca0b3e2795ba3afb6d1dc311b70df0f6 100644 (file)
@@ -69,5 +69,6 @@ func Test11925(t *testing.T)                 { test11925(t) }
 func Test12030(t *testing.T)                 { test12030(t) }
 func TestGCC68255(t *testing.T)              { testGCC68255(t) }
 func TestCallGoWithString(t *testing.T)      { testCallGoWithString(t) }
+func Test14838(t *testing.T)                 { test14838(t) }
 
 func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
diff --git a/misc/cgo/test/issue14838.go b/misc/cgo/test/issue14838.go
new file mode 100644 (file)
index 0000000..e6e1a42
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2016 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 14838. add CBytes function
+
+package cgotest
+
+/*
+#include <stdlib.h>
+
+int check_cbytes(char *b, size_t l) {
+       int i;
+       for (i = 0; i < l; i++) {
+               if (b[i] != i) {
+                       return 0;
+               }
+       }
+       return 1;
+}
+*/
+import "C"
+
+import (
+       "testing"
+       "unsafe"
+)
+
+func test14838(t *testing.T) {
+       data := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
+       cData := C.CBytes(data)
+       defer C.free(cData)
+
+       if C.check_cbytes((*C.char)(cData), C.size_t(len(data))) == 0 {
+               t.Fatalf("mismatched data: expected %v, got %v", data, (*(*[10]byte)(unsafe.Pointer(cData)))[:])
+       }
+}
index 61e480c58560cd209fce1af43517ee92f8bbe50e..6e0bfa58c6d23830e6c4d8dd64c0bf48b115289b 100644 (file)
@@ -198,6 +198,13 @@ by making copies of the data.  In pseudo-Go definitions:
        // if C.free is needed).
        func C.CString(string) *C.char
 
+       // Go []byte slice to C array
+       // The C array is allocated in the C heap using malloc.
+       // It is the caller's responsibility to arrange for it to be
+       // freed, such as by calling C.free (be sure to include stdlib.h
+       // if C.free is needed).
+       func C.CBytes([]byte) unsafe.Pointer
+
        // C string to Go string
        func C.GoString(*C.char) string
 
index 40c76b52e49c50187b60728cf35a46df38d62f6b..621c41c6b2352b678db0a313ac0c6f6b71936909 100644 (file)
@@ -533,6 +533,7 @@ func fixGo(name string) string {
 
 var isBuiltin = map[string]bool{
        "_Cfunc_CString":   true,
+       "_Cfunc_CBytes":    true,
        "_Cfunc_GoString":  true,
        "_Cfunc_GoStringN": true,
        "_Cfunc_GoBytes":   true,
@@ -1324,6 +1325,7 @@ _GoString_ GoString(char *p);
 _GoString_ GoStringN(char *p, int l);
 _GoBytes_ GoBytes(void *p, int n);
 char *CString(_GoString_);
+void *CBytes(_GoBytes_);
 void *_CMalloc(size_t);
 `
 
@@ -1389,6 +1391,15 @@ func _Cfunc_CString(s string) *_Ctype_char {
 }
 `
 
+const cBytesDef = `
+func _Cfunc_CBytes(b []byte) unsafe.Pointer {
+       p := _cgo_runtime_cmalloc(uintptr(len(b)))
+       pp := (*[1<<30]byte)(p)
+       copy(pp[:], b)
+       return p
+}
+`
+
 const cMallocDef = `
 func _Cfunc__CMalloc(n _Ctype_size_t) unsafe.Pointer {
        return _cgo_runtime_cmalloc(uintptr(n))
@@ -1400,6 +1411,7 @@ var builtinDefs = map[string]string{
        "GoStringN": goStringNDef,
        "GoBytes":   goBytesDef,
        "CString":   cStringDef,
+       "CBytes":    cBytesDef,
        "_CMalloc":  cMallocDef,
 }
 
@@ -1437,6 +1449,12 @@ const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) {
        return p;
 }
 
+void *_cgoPREFIX_Cfunc_CBytes(struct __go_open_array b) {
+       char *p = malloc(b.__count);
+       memmove(p, b.__data, b.__count);
+       return p;
+}
+
 struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) {
        intgo len = (p != NULL) ? strlen(p) : 0;
        return __go_byte_array_to_string(p, len);