1
0
mirror of https://github.com/golang/go synced 2024-11-24 21:00:09 -07:00

cgo: add GoBytes, fix gmp example

Fixes #1640.
Fixes #2007.

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/4815063
This commit is contained in:
Russ Cox 2011-07-28 12:39:50 -04:00
parent acb02ebc30
commit db9229def8
8 changed files with 55 additions and 4 deletions

View File

@ -265,7 +265,7 @@ func (z *Int) Mod(x, y *Int) *Int {
func (z *Int) Lsh(x *Int, s uint) *Int { func (z *Int) Lsh(x *Int, s uint) *Int {
x.doinit() x.doinit()
z.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 return z
} }
@ -273,7 +273,7 @@ func (z *Int) Lsh(x *Int, s uint) *Int {
func (z *Int) Rsh(x *Int, s uint) *Int { func (z *Int) Rsh(x *Int, s uint) *Int {
x.doinit() x.doinit()
z.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 return z
} }

View File

@ -42,3 +42,4 @@ func (f *File) Flush() {
} }
var Greeting = C.GoString(C.greeting) var Greeting = C.GoString(C.greeting)
var Gbytes = C.GoBytes(unsafe.Pointer(C.greeting), C.int(len(Greeting)))

View File

@ -189,6 +189,10 @@ func (f *File) saveExport(x interface{}, context string) {
error(c.Pos(), "export missing name") 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{ f.ExpFunc = append(f.ExpFunc, &ExpFunc{
Func: n, Func: n,
ExpName: name, ExpName: name,

View 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.short, C.ushort (unsigned short), C.int, C.uint (unsigned int),
C.long, C.ulong (unsigned long), C.longlong (long long), C.long, C.ulong (unsigned long), C.longlong (long long),
C.ulonglong (unsigned long long), C.float, C.double. 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 To access a struct, union, or enum type directly, prefix it with
struct_, union_, or enum_, as in C.struct_stat. 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 call accordingly, but Go cannot. In Go, you must pass
the pointer to the first element explicitly: C.f(&x[0]). 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 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. files, a C file for 6c (or 8c or 5c), and a C file for gcc.

View File

@ -1140,6 +1140,14 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
t.Align = c.ptrSize t.Align = c.ptrSize
break 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) name := c.Ident("_Ctypedef_" + dt.Name)
t.Go = name // publish before recursive call t.Go = name // publish before recursive call
sub := c.Type(dt.Type) sub := c.Type(dt.Type)

View File

@ -236,7 +236,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
printer.Fprint(fgo2, fset, d) printer.Fprint(fgo2, fset, d)
fmt.Fprintf(fgo2, "\n") 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. // The builtins are already defined in the C prolog.
return return
} }
@ -316,7 +316,7 @@ func (p *Package) writeOutput(f *File, srcfile string) {
func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
name := n.Mangle 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 // The builtins are already defined in the C prolog, and we don't
// want to duplicate function definitions we've already done. // want to duplicate function definitions we've already done.
return return
@ -646,6 +646,8 @@ func (p *Package) cgoType(e ast.Expr) *Type {
} }
return r return r
} }
error(e.Pos(), "unrecognized Go type %s", t.Name)
return &Type{Size: 4, Align: 4, C: c("int")}
case *ast.SelectorExpr: case *ast.SelectorExpr:
id, ok := t.X.(*ast.Ident) id, ok := t.X.(*ast.Ident)
if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" { if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" {
@ -679,8 +681,10 @@ __cgo_size_assert(double, 8)
const builtinProlog = ` const builtinProlog = `
typedef struct { char *p; int n; } _GoString_; typedef struct { char *p; int n; } _GoString_;
typedef struct { char *p; int n; int c; } _GoBytes_;
_GoString_ GoString(char *p); _GoString_ GoString(char *p);
_GoString_ GoStringN(char *p, int l); _GoString_ GoStringN(char *p, int l);
_GoBytes_ GoBytes(void *p, int n);
char *CString(_GoString_); char *CString(_GoString_);
` `
@ -704,6 +708,13 @@ void
FLUSH(&s); FLUSH(&s);
} }
void
·_Cfunc_GoBytes(int8 *p, int32 l, Slice s)
{
s = runtime·gobytes((byte*)p, l);
FLUSH(&s);
}
void void
·_Cfunc_CString(String s, int8 *p) ·_Cfunc_CString(String s, int8 *p)
{ {

View File

@ -413,6 +413,7 @@ void* runtime·mal(uintptr);
String runtime·catstring(String, String); String runtime·catstring(String, String);
String runtime·gostring(byte*); String runtime·gostring(byte*);
String runtime·gostringn(byte*, int32); String runtime·gostringn(byte*, int32);
Slice runtime·gobytes(byte*, int32);
String runtime·gostringnocopy(byte*); String runtime·gostringnocopy(byte*);
String runtime·gostringw(uint16*); String runtime·gostringw(uint16*);
void runtime·initsig(int32); void runtime·initsig(int32);

View File

@ -74,6 +74,16 @@ runtime·gostringn(byte *str, int32 l)
return s; 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 String
runtime·gostringnocopy(byte *str) runtime·gostringnocopy(byte *str)
{ {