aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2011-07-28 12:39:50 -0400
committerRuss Cox <rsc@golang.org>2011-07-28 12:39:50 -0400
commitdb9229def8bb23cf254e5027eaf9b5914220e621 (patch)
tree8f4b7ad144d6bcb74f06ad9592e66c4bceac90c5
parentacb02ebc30bef25318505108d801d073508c0c6e (diff)
downloadgo-db9229def8bb23cf254e5027eaf9b5914220e621.tar.gz
go-db9229def8bb23cf254e5027eaf9b5914220e621.zip
cgo: add GoBytes, fix gmp example
Fixes #1640. Fixes #2007. R=golang-dev, adg CC=golang-dev https://golang.org/cl/4815063
-rw-r--r--misc/cgo/gmp/gmp.go4
-rw-r--r--misc/cgo/stdio/file.go1
-rw-r--r--src/cmd/cgo/ast.go4
-rw-r--r--src/cmd/cgo/doc.go16
-rw-r--r--src/cmd/cgo/gcc.go8
-rw-r--r--src/cmd/cgo/out.go15
-rw-r--r--src/pkg/runtime/runtime.h1
-rw-r--r--src/pkg/runtime/string.goc10
8 files changed, 55 insertions, 4 deletions
diff --git a/misc/cgo/gmp/gmp.go b/misc/cgo/gmp/gmp.go
index 10933498db..3dbc022ce5 100644
--- a/misc/cgo/gmp/gmp.go
+++ b/misc/cgo/gmp/gmp.go
@@ -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
}
diff --git a/misc/cgo/stdio/file.go b/misc/cgo/stdio/file.go
index 021cbf909c..ab1e88436c 100644
--- a/misc/cgo/stdio/file.go
+++ b/misc/cgo/stdio/file.go
@@ -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)))
diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go
index 46e33686d2..73b7313d67 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 064725c1d5..63413825af 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 a4d83f1e7f..7ec4d8ccf9 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 1dde2d935d..9c962b8ff9 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
@@ -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,6 +709,13 @@ 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);
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 50c2b0eeca..15b1e8eb9d 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -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);
diff --git a/src/pkg/runtime/string.goc b/src/pkg/runtime/string.goc
index 34b167791e..e0daac49ab 100644
--- a/src/pkg/runtime/string.goc
+++ b/src/pkg/runtime/string.goc
@@ -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)
{