]> Cypherpunks repositories - gostls13.git/commitdiff
cgo: add GoBytes, fix gmp example
authorRuss Cox <rsc@golang.org>
Thu, 28 Jul 2011 16:39:50 +0000 (12:39 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 28 Jul 2011 16:39:50 +0000 (12:39 -0400)
Fixes #1640.
Fixes #2007.

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/4815063

misc/cgo/gmp/gmp.go
misc/cgo/stdio/file.go
src/cmd/cgo/ast.go
src/cmd/cgo/doc.go
src/cmd/cgo/gcc.go
src/cmd/cgo/out.go
src/pkg/runtime/runtime.h
src/pkg/runtime/string.goc

index 10933498db8d5afeaa623c3c0965d6e051beacab..3dbc022ce539f51094260bf714ce7c0a3a4b2992 100644 (file)
@@ -265,7 +265,7 @@ func (z *Int) Mod(x, y *Int) *Int {
 func (z *Int) Lsh(x *Int, s uint) *Int {
        x.doinit()
        z.doinit()
-       C.mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(s))
+       C.mpz_mul_2exp(&z.i[0], &x.i[0], C.mp_bitcnt_t(s))
        return z
 }
 
@@ -273,7 +273,7 @@ func (z *Int) Lsh(x *Int, s uint) *Int {
 func (z *Int) Rsh(x *Int, s uint) *Int {
        x.doinit()
        z.doinit()
-       C.mpz_div_2exp(&z.i[0], &x.i[0], C.ulong(s))
+       C.mpz_div_2exp(&z.i[0], &x.i[0], C.mp_bitcnt_t(s))
        return z
 }
 
index 021cbf909caf2598398d0e9197cce794ab6efa9d..ab1e88436c94901241d190e8cd43047a1677a301 100644 (file)
@@ -42,3 +42,4 @@ func (f *File) Flush() {
 }
 
 var Greeting = C.GoString(C.greeting)
+var Gbytes = C.GoBytes(unsafe.Pointer(C.greeting), C.int(len(Greeting)))
index 46e33686d209d5a1458ca069a5b07d49b3792dbc..73b7313d675c103f60d4a8eb2e96c83f7e6809b0 100644 (file)
@@ -189,6 +189,10 @@ func (f *File) saveExport(x interface{}, context string) {
                        error(c.Pos(), "export missing name")
                }
 
+               if name != n.Name.Name {
+                       error(c.Pos(), "export comment has wrong name %q, want %q", name, n.Name.Name)
+               }
+
                f.ExpFunc = append(f.ExpFunc, &ExpFunc{
                        Func:    n,
                        ExpName: name,
index 064725c1d5dbc43f26202ed8553034f6fab9ce33..63413825af59dfae9ddf3b907fccce9f4f4c01fc 100644 (file)
@@ -52,6 +52,7 @@ C.char, C.schar (signed char), C.uchar (unsigned char),
 C.short, C.ushort (unsigned short), C.int, C.uint (unsigned int),
 C.long, C.ulong (unsigned long), C.longlong (long long),
 C.ulonglong (unsigned long long), C.float, C.double.
+The C type void* is represented by Go's unsafe.Pointer.
 
 To access a struct, union, or enum type directly, prefix it with
 struct_, union_, or enum_, as in C.struct_stat.
@@ -68,6 +69,21 @@ C compilers are aware of this calling convention and adjust
 the call accordingly, but Go cannot.  In Go, you must pass
 the pointer to the first element explicitly: C.f(&x[0]).
 
+A few special functions convert between Go and C types
+by making copies of the data.  In pseudo-Go definitions:
+
+       // Go string to C string
+       func C.CString(string) *C.char
+
+       // C string to Go string
+       func C.GoString(*C.char) string
+
+       // C string, length to Go string
+       func C.GoStringN(*C.char, C.int) string
+
+       // C pointer, length to Go []byte
+       func C.GoBytes(unsafe.Pointer, C.int) []byte
+
 Cgo transforms the input file into four output files: two Go source
 files, a C file for 6c (or 8c or 5c), and a C file for gcc.
 
index a4d83f1e7feb6ad33029f542e39702b1155637e2..7ec4d8ccf965f7bcc84406b6409eb905dea50c00 100644 (file)
@@ -1140,6 +1140,14 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
                        t.Align = c.ptrSize
                        break
                }
+               if dt.Name == "_GoBytes_" {
+                       // Special C name for Go []byte type.
+                       // Knows slice layout used by compilers: pointer, length, cap.
+                       t.Go = c.Ident("[]byte")
+                       t.Size = c.ptrSize + 4 + 4
+                       t.Align = c.ptrSize
+                       break
+               }
                name := c.Ident("_Ctypedef_" + dt.Name)
                t.Go = name // publish before recursive call
                sub := c.Type(dt.Type)
index 1dde2d935d93195d4c1d7232a91b32b3023cb3f1..9c962b8ff9edb36daea53820f142c49b9d119e47 100644 (file)
@@ -236,7 +236,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
        printer.Fprint(fgo2, fset, d)
        fmt.Fprintf(fgo2, "\n")
 
-       if name == "CString" || name == "GoString" || name == "GoStringN" {
+       if name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" {
                // The builtins are already defined in the C prolog.
                return
        }
@@ -316,7 +316,7 @@ func (p *Package) writeOutput(f *File, srcfile string) {
 
 func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
        name := n.Mangle
-       if name == "_Cfunc_CString" || name == "_Cfunc_GoString" || name == "_Cfunc_GoStringN" || p.Written[name] {
+       if name == "_Cfunc_CString" || name == "_Cfunc_GoString" || name == "_Cfunc_GoStringN" || name == "_Cfunc_GoBytes" || p.Written[name] {
                // The builtins are already defined in the C prolog, and we don't
                // want to duplicate function definitions we've already done.
                return
@@ -646,6 +646,8 @@ func (p *Package) cgoType(e ast.Expr) *Type {
                        }
                        return r
                }
+               error(e.Pos(), "unrecognized Go type %s", t.Name)
+               return &Type{Size: 4, Align: 4, C: c("int")}
        case *ast.SelectorExpr:
                id, ok := t.X.(*ast.Ident)
                if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" {
@@ -679,8 +681,10 @@ __cgo_size_assert(double, 8)
 
 const builtinProlog = `
 typedef struct { char *p; int n; } _GoString_;
+typedef struct { char *p; int n; int c; } _GoBytes_;
 _GoString_ GoString(char *p);
 _GoString_ GoStringN(char *p, int l);
+_GoBytes_ GoBytes(void *p, int n);
 char *CString(_GoString_);
 `
 
@@ -704,6 +708,13 @@ void
        FLUSH(&s);
 }
 
+void
+·_Cfunc_GoBytes(int8 *p, int32 l, Slice s)
+{
+       s = runtime·gobytes((byte*)p, l);
+       FLUSH(&s);
+}
+
 void
 ·_Cfunc_CString(String s, int8 *p)
 {
index 50c2b0eeca23064b698cd7aca1b84b305d8f34ae..15b1e8eb9d8c1282e7fa20e62d29fb9cbbfc35fb 100644 (file)
@@ -413,6 +413,7 @@ void*       runtime·mal(uintptr);
 String runtime·catstring(String, String);
 String runtime·gostring(byte*);
 String  runtime·gostringn(byte*, int32);
+Slice  runtime·gobytes(byte*, int32);
 String runtime·gostringnocopy(byte*);
 String runtime·gostringw(uint16*);
 void   runtime·initsig(int32);
index 34b167791e436e667e44042f6d62b0be2dd7ed3a..e0daac49ab6b095209b19b54806c5895a61300a4 100644 (file)
@@ -74,6 +74,16 @@ runtime·gostringn(byte *str, int32 l)
        return s;
 }
 
+Slice
+runtime·gobytes(byte *p, int32 n)
+{
+       Slice sl;
+
+       sl.array = runtime·mallocgc(n, FlagNoPointers, 1, 0);
+       runtime·memmove(sl.array, p, n);
+       return sl;
+}
+
 String
 runtime·gostringnocopy(byte *str)
 {