diff options
| author | Ondřej Surý <ondrej@sury.org> | 2011-08-03 17:26:15 +0200 |
|---|---|---|
| committer | Ondřej Surý <ondrej@sury.org> | 2011-08-03 17:31:49 +0200 |
| commit | b757d264230d65f988e08158e096a09497d39eb4 (patch) | |
| tree | e20ec608a2ec8ebf603fa7aa060eb9723c4780b9 /src/cmd/cgo | |
| parent | 5976088995f5c0d0bcada7d491fda4b6245e54e0 (diff) | |
| download | golang-b757d264230d65f988e08158e096a09497d39eb4.tar.gz | |
Imported Upstream version 2011.07.29
Diffstat (limited to 'src/cmd/cgo')
| -rw-r--r-- | src/cmd/cgo/ast.go | 4 | ||||
| -rw-r--r-- | src/cmd/cgo/doc.go | 16 | ||||
| -rw-r--r-- | src/cmd/cgo/gcc.go | 8 | ||||
| -rw-r--r-- | src/cmd/cgo/out.go | 19 |
4 files changed, 43 insertions, 4 deletions
diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go index 46e33686d..73b7313d6 100644 --- a/src/cmd/cgo/ast.go +++ b/src/cmd/cgo/ast.go @@ -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, diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go index 064725c1d..63413825a 100644 --- a/src/cmd/cgo/doc.go +++ b/src/cmd/cgo/doc.go @@ -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. diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index a4d83f1e7..7ec4d8ccf 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -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) diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 6802dd1cf..9c962b8ff 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -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 @@ -412,7 +412,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) { t := p.cgoType(atype) if off%t.Align != 0 { pad := t.Align - off%t.Align - ctype += fmt.Sprintf("\t\tchar __pad%d[%d]\n", npad, pad) + ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) off += pad npad++ } @@ -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_); ` @@ -705,10 +709,17 @@ void } void +·_Cfunc_GoBytes(int8 *p, int32 l, Slice s) +{ + s = runtime·gobytes((byte*)p, l); + FLUSH(&s); +} + +void ·_Cfunc_CString(String s, int8 *p) { p = runtime·cmalloc(s.len+1); - runtime·mcpy((byte*)p, s.str, s.len); + runtime·memmove((byte*)p, s.str, s.len); p[s.len] = 0; FLUSH(&p); } |
