all: first stab at no-cgo-ptr

This commit is contained in:
Sebastien Binet 2017-09-27 18:29:58 +02:00
parent 7cb9dcd10f
commit 9240dfc24a
4 changed files with 89 additions and 64 deletions

View File

@ -122,9 +122,8 @@ class _cffi_helper(object):
@staticmethod
def cffi_cgopy_cnv_c2py_string(c):
s = _cffi_helper.lib._cgopy_CString(c)
pystr = ffi.string(s)
_cffi_helper.lib._cgopy_FreeCString(s)
pystr = ffi.string(c)
_cffi_helper.lib._cgopy_FreeCString(c)
if _PY3:
pystr = pystr.decode('utf8')
return pystr

View File

@ -239,10 +239,10 @@ func (g *cffiGen) genCdefStructMemberSetter(s Struct, i int, f types.Object) {
// genCdefStructTPStr generates C definitions of str method for a Go struct.
func (g *cffiGen) genCdefStructTPStr(s Struct) {
g.wrapper.Printf("extern GoString cgo_func_%[1]s_str(void* p0);\n", s.sym.id)
g.wrapper.Printf("extern const char* cgo_func_%[1]s_str(void* p0);\n", s.sym.id)
}
// genCdefTypeTPStr generates C definitions of str method for a Go type.
func (g *cffiGen) genCdefTypeTPStr(sym *symbol) {
g.wrapper.Printf("extern GoString cgo_func_%[1]s_str(%[2]s p0);\n", sym.id, sym.cgoname)
g.wrapper.Printf("extern const char* cgo_func_%[1]s_str(%[2]s p0);\n", sym.id, sym.cgoname)
}

View File

@ -41,7 +41,7 @@ func (g *cffiGen) genStructConversion(s Struct) {
g.wrapper.Printf("def cffi_cgopy_cnv_c2py_%[1]s_%[2]s(c):\n", s.Package().Name(), s.GoName())
g.wrapper.Indent()
g.wrapper.Printf("o = %[1]s()\n", s.GoName())
g.wrapper.Printf("o.cgopy = ffi.gc(c, _cffi_helper.lib.cgopy_decref)\n")
//g.wrapper.Printf("o.cgopy = ffi.gc(c, _cffi_helper.lib.cgopy_decref)\n")
g.wrapper.Printf("return o\n\n")
g.wrapper.Outdent()
}

View File

@ -20,26 +20,27 @@ const (
checkGoVersion = "_cgopy_CheckGoVersion()"
checkGoVersionDef = `
func _cgopy_CheckGoVersion() {
godebug := os.Getenv("GODEBUG")
cgocheck := -1
var err error
if godebug != "" {
const prefix = "cgocheck="
for _, option := range strings.Split(godebug, ",") {
if !strings.HasPrefix(option, prefix) {
continue
}
cgocheck, err = strconv.Atoi(option[len(prefix):])
if err != nil {
cgocheck = -1
fmt.Fprintf(os.Stderr, "gopy: invalid cgocheck value %q (expected an integer)\n", option)
}
}
}
godebug := os.Getenv("GODEBUG")
cgocheck := -1
var err error
if cgocheck != 0 {
fmt.Fprintf(os.Stderr, "gopy: GODEBUG=cgocheck=0 should be set for Go>=1.6\n")
}
if godebug != "" {
const prefix = "cgocheck="
for _, option := range strings.Split(godebug, ",") {
if !strings.HasPrefix(option, prefix) {
continue
}
cgocheck, err = strconv.Atoi(option[len(prefix):])
if err != nil {
cgocheck = -1
fmt.Fprintf(os.Stderr, "gopy: invalid cgocheck value %q (expected an integer)\n", option)
}
}
}
if cgocheck != 0 {
fmt.Fprintf(os.Stderr, "gopy: GODEBUG=cgocheck=0 should be set for Go>=1.6\n")
}
}
`
goPreamble = `// Package main is an autogenerated binder stub for package %[1]s.
@ -158,6 +159,28 @@ func cgopy_decref(ptr unsafe.Pointer) {
refs.Unlock()
}
//export cgopy_get_ptr
func cgopy_get_ptr(id int32) unsafe.Pointer {
refs.Lock()
cobj, ok := refs.ptrs[id]
refs.Unlock()
if !ok {
panic(fmt.Errorf("cgopy: unknown id %%d", id))
}
return cobj.ptr
}
//export cgopy_get_id
func cgopy_get_id(ptr unsafe.Pointer) int32 {
refs.Lock()
id, ok := refs.refs[ptr]
refs.Unlock()
if !ok {
panic(fmt.Errorf("cgopy: unknown ptr %%+x", ptr))
}
return id
}
%[5]s
func init() {
@ -287,7 +310,7 @@ func (g *goGen) genFuncBody(f Func) {
head := arg.Name()
if arg.needWrap() {
head = fmt.Sprintf(
"*(*%s)(unsafe.Pointer(%s))",
"*(*%s)(cgopy_get_ptr(int32(%s)))",
types.TypeString(
arg.GoType(),
func(*types.Package) string { return g.pkg.Name() },
@ -319,11 +342,11 @@ func (g *goGen) genFuncBody(f Func) {
// g.Printf("")
// }
if res.needWrap() {
g.Printf("%s(unsafe.Pointer(&", res.sym.cgoname)
g.Printf("%s(cgopy_get_id(unsafe.Pointer(&", res.sym.cgoname)
}
g.Printf("_gopy_%03d", i)
if res.needWrap() {
g.Printf("))")
g.Printf(")))")
}
}
g.Printf("\n")
@ -335,7 +358,7 @@ func (g *goGen) genStruct(s Struct) {
g.Printf("\n// --- wrapping %s ---\n\n", s.sym.gofmt())
g.Printf("//export %[1]s\n", s.sym.cgoname)
g.Printf("// %[1]s wraps %[2]s\n", s.sym.cgoname, s.sym.gofmt())
g.Printf("type %[1]s unsafe.Pointer\n\n", s.sym.cgoname)
g.Printf("type %[1]s int32\n\n", s.sym.cgoname)
for i := 0; i < typ.NumFields(); i++ {
f := typ.Field(i)
@ -349,7 +372,7 @@ func (g *goGen) genStruct(s Struct) {
if needWrapType(ft) {
ftname = fmt.Sprintf("cgo_type_%[1]s_field_%d", s.ID(), i+1)
g.Printf("//export %s\n", ftname)
g.Printf("type %s unsafe.Pointer\n\n", ftname)
g.Printf("type %s int32\n\n", ftname)
}
// -- getter --
@ -361,13 +384,14 @@ func (g *goGen) genStruct(s Struct) {
)
g.Indent()
g.Printf(
"ret := (*%[1]s)(unsafe.Pointer(self))\n",
"ret := (*%[1]s)(cgopy_get_ptr(self))\n",
s.sym.gofmt(),
)
if !fsym.isBasic() {
g.Printf("cgopy_incref(unsafe.Pointer(&ret.%s))\n", f.Name())
g.Printf("return %s(unsafe.Pointer(&ret.%s))\n", ftname, f.Name())
g.Printf("ptr := unsafe.Pointer(&ret.%s)\n", f.Name())
g.Printf("cgopy_incref(ptr)\n")
g.Printf("return %s(cgopy_get_id(ptr))\n", ftname)
} else {
g.Printf("return ret.%s\n", f.Name())
}
@ -382,10 +406,10 @@ func (g *goGen) genStruct(s Struct) {
g.Indent()
fset := "v"
if !fsym.isBasic() {
fset = fmt.Sprintf("*(*%s)(unsafe.Pointer(v))", fsym.gofmt())
fset = fmt.Sprintf("*(*%s)(cgopy_get_ptr(v))", fsym.gofmt())
}
g.Printf(
"(*%[1]s)(unsafe.Pointer(self)).%[2]s = %[3]s\n",
"(*%[1]s)(cgopy_get_ptr(int32(self))).%[2]s = %[3]s\n",
s.sym.gofmt(),
f.Name(),
fset,
@ -402,8 +426,9 @@ func (g *goGen) genStruct(s Struct) {
g.Printf("func cgo_func_%[1]s_new() cgo_type_%[1]s {\n", s.ID())
g.Indent()
g.Printf("o := %[1]s{}\n", s.sym.gofmt())
g.Printf("cgopy_incref(unsafe.Pointer(&o))\n")
g.Printf("return (cgo_type_%[1]s)(unsafe.Pointer(&o))\n", s.ID())
g.Printf("ptr := unsafe.Pointer(&o)\n")
g.Printf("cgopy_incref(ptr)\n")
g.Printf("return cgo_type_%[1]s(cgopy_get_id(ptr))\n", s.ID())
g.Outdent()
g.Printf("}\n\n")
@ -418,7 +443,7 @@ func (g *goGen) genStruct(s Struct) {
if s.sym.isBasic() {
g.Printf("%[1]s(self)\n", s.sym.gofmt())
} else {
g.Printf("*(*%[1]s)(unsafe.Pointer(self))\n", s.sym.gofmt())
g.Printf("*(*%[1]s)(cgopy_get_ptr(int32(self)))\n", s.sym.gofmt())
}
g.Printf("return v\n")
g.Outdent()
@ -427,16 +452,16 @@ func (g *goGen) genStruct(s Struct) {
// support for __str__
g.Printf("//export cgo_func_%[1]s_str\n", s.ID())
g.Printf(
"func cgo_func_%[1]s_str(self %[2]s) string {\n",
"func cgo_func_%[1]s_str(self %[2]s) *C.char {\n",
s.ID(),
s.sym.cgoname,
)
g.Indent()
if (s.prots & ProtoStringer) == 0 {
g.Printf("return fmt.Sprintf(\"%%#v\", ")
g.Printf("*(*%[1]s)(unsafe.Pointer(self)))\n", s.sym.gofmt())
g.Printf("return C.CString(fmt.Sprintf(\"%%#v\", ")
g.Printf("*(*%[1]s)(cgopy_get_ptr(int32(self)))))\n", s.sym.gofmt())
} else {
g.Printf("return (*%[1]s)(unsafe.Pointer(self)).String()\n",
g.Printf("return C.CString((*%[1]s)(cgopy_get_ptr(int32(self))).String())\n",
s.sym.gofmt(),
)
}
@ -478,7 +503,7 @@ func (g *goGen) genMethodBody(s Struct, m Func) {
g.Printf(" := ")
}
g.Printf("(*%s)(unsafe.Pointer(self)).%s(",
g.Printf("(*%s)(cgopy_get_ptr(int32(self))).%s(",
s.sym.gofmt(),
m.GoName(),
)
@ -490,7 +515,7 @@ func (g *goGen) genMethodBody(s Struct, m Func) {
tail = ", "
}
if arg.sym.isStruct() {
g.Printf("*(*%s)(unsafe.Pointer(%s))%s", arg.sym.gofmt(), arg.Name(), tail)
g.Printf("*(*%s)(cgopy_get_ptr(int32(%s)))%s", arg.sym.gofmt(), arg.Name(), tail)
} else {
g.Printf("%s%s", arg.Name(), tail)
}
@ -517,11 +542,11 @@ func (g *goGen) genMethodBody(s Struct, m Func) {
// g.Printf("")
// }
if res.needWrap() {
g.Printf("%s(unsafe.Pointer(&", res.sym.cgoname)
g.Printf("%s(cgopy_get_id(unsafe.Pointer(&", res.sym.cgoname)
}
g.Printf("_gopy_%03d", i)
if res.needWrap() {
g.Printf("))")
g.Printf(")))")
}
}
g.Printf("\n")
@ -597,7 +622,7 @@ func (g *goGen) genType(sym *symbol) {
btyp := sym.GoType().Underlying().String()
g.Printf("type %[1]s %[2]s\n\n", sym.cgoname, btyp)
} else {
g.Printf("type %[1]s unsafe.Pointer\n\n", sym.cgoname)
g.Printf("type %[1]s int32\n\n", sym.cgoname)
}
g.Printf("//export cgo_func_%[1]s_new\n", sym.id)
g.Printf("func cgo_func_%[1]s_new() %[2]s {\n", sym.id, sym.cgoname)
@ -606,8 +631,9 @@ func (g *goGen) genType(sym *symbol) {
if sym.isBasic() {
g.Printf("return %[1]s(o)\n", sym.cgoname)
} else {
g.Printf("cgopy_incref(unsafe.Pointer(&o))\n")
g.Printf("return (%[1]s)(unsafe.Pointer(&o))\n", sym.cgoname)
g.Printf("ptr := unsafe.Pointer(&o)\n")
g.Printf("cgopy_incref(ptr)\n")
g.Printf("return %[1]s(cgopy_get_id(ptr))\n", sym.cgoname)
}
g.Outdent()
g.Printf("}\n\n")
@ -623,7 +649,7 @@ func (g *goGen) genType(sym *symbol) {
if sym.isBasic() {
g.Printf("%[1]s(self)\n", sym.gofmt())
} else {
g.Printf("*(*%[1]s)(unsafe.Pointer(self))\n", sym.gofmt())
g.Printf("*(*%[1]s)(cgopy_get_ptr(int32(self)))\n", sym.gofmt())
}
g.Printf("return v\n")
g.Outdent()
@ -632,16 +658,16 @@ func (g *goGen) genType(sym *symbol) {
// support for __str__
g.Printf("//export cgo_func_%[1]s_str\n", sym.id)
g.Printf(
"func cgo_func_%[1]s_str(self %[2]s) string {\n",
"func cgo_func_%[1]s_str(self %[2]s) *C.char {\n",
sym.id,
sym.cgoname,
)
g.Indent()
g.Printf("return fmt.Sprintf(\"%%#v\", ")
g.Printf("return C.CString(fmt.Sprintf(\"%%#v\", ")
if sym.isBasic() {
g.Printf("%[1]s(self))\n", sym.gofmt())
g.Printf("%[1]s(self)))\n", sym.gofmt())
} else {
g.Printf("*(*%[1]s)(unsafe.Pointer(self)))\n", sym.gofmt())
g.Printf("*(*%[1]s)(cgopy_get_ptr(int32(self)))))\n", sym.gofmt())
}
g.Outdent()
g.Printf("}\n\n")
@ -681,11 +707,11 @@ func (g *goGen) genType(sym *symbol) {
esym.cgotypename(),
)
g.Indent()
g.Printf("arr := (*%[1]s)(unsafe.Pointer(self))\n", sym.gofmt())
g.Printf("arr := (*%[1]s)(cgopy_get_ptr(self))\n", sym.gofmt())
g.Printf("elt := (*arr)[i]\n")
if !esym.isBasic() {
g.Printf("cgopy_incref(unsafe.Pointer(&elt))\n")
g.Printf("return (%[1]s)(unsafe.Pointer(&elt))\n", esym.cgotypename())
g.Printf("return %[1]s(cgopy_get_id(unsafe.Pointer(&elt)))\n", esym.cgotypename())
} else {
if esym.isNamed() {
g.Printf("return %[1]s(elt)\n", esym.cgotypename())
@ -704,10 +730,10 @@ func (g *goGen) genType(sym *symbol) {
esym.cgotypename(),
)
g.Indent()
g.Printf("arr := (*%[1]s)(unsafe.Pointer(self))\n", sym.gofmt())
g.Printf("arr := (*%[1]s)(cgopy_get_ptr(self))\n", sym.gofmt())
g.Printf("(*arr)[i] = ")
if !esym.isBasic() {
g.Printf("*(*%[1]s)(unsafe.Pointer(v))\n", esym.gofmt())
g.Printf("*(*%[1]s)(cgopy_get_ptr(v))\n", esym.gofmt())
} else {
if esym.isNamed() {
g.Printf("%[1]s(v)\n", esym.gofmt())
@ -736,10 +762,10 @@ func (g *goGen) genType(sym *symbol) {
esym.cgotypename(),
)
g.Indent()
g.Printf("slice := (*%[1]s)(unsafe.Pointer(self))\n", sym.gofmt())
g.Printf("slice := (*%[1]s)(cgopy_get_ptr(self))\n", sym.gofmt())
g.Printf("*slice = append(*slice, ")
if !esym.isBasic() {
g.Printf("*(*%[1]s)(unsafe.Pointer(v))", esym.gofmt())
g.Printf("*(*%[1]s)(cgopy_get_ptr(v))", esym.gofmt())
} else {
if esym.isNamed() {
g.Printf("%[1]s(v)", esym.gofmt())
@ -1045,7 +1071,7 @@ func (g *goGen) genTypeMethods(sym *symbol) {
msym.goname,
)
} else {
g.Printf("(*%s)(unsafe.Pointer(self)).%s(",
g.Printf("(*%s)(cgopy_get_ptr(int32(self))).%s(",
sym.gofmt(),
msym.goname,
)
@ -1058,7 +1084,7 @@ func (g *goGen) genTypeMethods(sym *symbol) {
}
sarg := g.pkg.syms.symtype(params.At(i).Type())
if needWrapType(sarg.GoType()) {
g.Printf("*(*%s)(unsafe.Pointer(arg%03d))",
g.Printf("*(*%s)(cgopy_get_ptr(int32(arg%03d)))",
sarg.gofmt(),
i,
)
@ -1083,13 +1109,13 @@ func (g *goGen) genTypeMethods(sym *symbol) {
sret := g.pkg.syms.symtype(res.At(i).Type())
if needWrapType(sret.GoType()) {
g.Printf(
"%s(unsafe.Pointer(&",
"%s(cgopy_get_id(unsafe.Pointer(&",
sret.cgoname,
)
}
g.Printf("res%03d", i)
if needWrapType(sret.GoType()) {
g.Printf("))")
g.Printf(")))")
}
}
g.Printf("\n")