From 9240dfc24a28145b788254c4fd6c75f92a1adf9a Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Wed, 27 Sep 2017 18:29:58 +0200 Subject: [PATCH] all: first stab at no-cgo-ptr --- bind/gencffi.go | 5 +- bind/gencffi_cdef.go | 4 +- bind/gencffi_struct.go | 2 +- bind/gengo.go | 142 ++++++++++++++++++++++++----------------- 4 files changed, 89 insertions(+), 64 deletions(-) diff --git a/bind/gencffi.go b/bind/gencffi.go index e39e99a..051f974 100644 --- a/bind/gencffi.go +++ b/bind/gencffi.go @@ -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 diff --git a/bind/gencffi_cdef.go b/bind/gencffi_cdef.go index 3e97357..8b03795 100644 --- a/bind/gencffi_cdef.go +++ b/bind/gencffi_cdef.go @@ -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) } diff --git a/bind/gencffi_struct.go b/bind/gencffi_struct.go index b918cb7..9c251eb 100644 --- a/bind/gencffi_struct.go +++ b/bind/gencffi_struct.go @@ -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() } diff --git a/bind/gengo.go b/bind/gengo.go index f033327..12d5df1 100644 --- a/bind/gengo.go +++ b/bind/gengo.go @@ -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")