diff --git a/bind/gen_func.go b/bind/gen_func.go index d2c6dca..becdac5 100644 --- a/bind/gen_func.go +++ b/bind/gen_func.go @@ -15,6 +15,10 @@ import ( func (g *pybindGen) genFuncSig(sym *symbol, fsym Func) bool { isMethod := (sym != nil) + if fsym.sig == nil { + return false + } + sig := fsym.sig args := sig.Params() res := sig.Results() @@ -175,6 +179,9 @@ if err != nil { g.gofile.Indent() if nres > 0 { ret := res[0] + if ret.sym.zval == "" { + fmt.Printf("gopy: programmer error: empty zval zero value in symbol: %v\n", ret.sym) + } if ret.sym.go2py != "" { g.gofile.Printf("return %s(%s)\n", ret.sym.go2py, ret.sym.zval) } else { @@ -216,9 +223,9 @@ if err != nil { na := "" if arg.sym.py2go != "" { if arg.sym.hasHandle() && !arg.sym.isPtrOrIface() { - na = fmt.Sprintf("*%s(%s)", arg.sym.py2go, arg.Name()) + na = fmt.Sprintf("*%s(%s)%s", arg.sym.py2go, arg.Name(), arg.sym.py2goParenEx) } else { - na = fmt.Sprintf("%s(%s)", arg.sym.py2go, arg.Name()) + na = fmt.Sprintf("%s(%s)%s", arg.sym.py2go, arg.Name(), arg.sym.py2goParenEx) } } else { na = arg.Name() diff --git a/bind/gen_slice.go b/bind/gen_slice.go index 3f72e52..5dbc5fe 100644 --- a/bind/gen_slice.go +++ b/bind/gen_slice.go @@ -149,7 +149,7 @@ otherwise parameter is a python list that we copy from g.gofile.Indent() g.gofile.Printf("s := *ptrFmHandle_%s(handle)\n", slNm) if esym.py2go != "" { - g.gofile.Printf("s[idx] = %s(value)\n", esym.py2go) + g.gofile.Printf("s[idx] = %s(value)%s\n", esym.py2go, esym.py2goParenEx) } else { g.gofile.Printf("s[idx] = value\n") } @@ -163,7 +163,7 @@ otherwise parameter is a python list that we copy from g.gofile.Indent() g.gofile.Printf("s := ptrFmHandle_%s(handle)\n", slNm) if esym.py2go != "" { - g.gofile.Printf("*s = append(*s, %s(value))\n", esym.py2go) + g.gofile.Printf("*s = append(*s, %s(value)%s)\n", esym.py2go, esym.py2goParenEx) } else { g.gofile.Printf("*s = append(*s, value)\n") } diff --git a/bind/gen_struct.go b/bind/gen_struct.go index de4419f..6fb8f1c 100644 --- a/bind/gen_struct.go +++ b/bind/gen_struct.go @@ -105,7 +105,7 @@ func (g *pybindGen) genStructMembers(s Struct) { typ := s.Struct() for i := 0; i < typ.NumFields(); i++ { f := typ.Field(i) - if !f.Exported() { + if !f.Exported() || f.Embedded() { continue } g.genStructMemberGetter(s, i, f) @@ -178,9 +178,9 @@ func (g *pybindGen) genStructMemberSetter(s Struct, i int, f types.Object) { g.gofile.Printf("op := ptrFmHandle_%s(handle)\n", s.GoName()) if ret.go2py != "" { if ret.hasHandle() && !ret.isPtrOrIface() { - g.gofile.Printf("op.%s = *%s(val)", f.Name(), ret.py2go) + g.gofile.Printf("op.%s = *%s(val)%s", f.Name(), ret.py2go, ret.py2goParenEx) } else { - g.gofile.Printf("op.%s = %s(val)", f.Name(), ret.py2go) + g.gofile.Printf("op.%s = %s(val)%s", f.Name(), ret.py2go, ret.py2goParenEx) } } else { g.gofile.Printf("op.%s = val", f.Name()) diff --git a/bind/gen_type.go b/bind/gen_type.go index 369e516..25d62f0 100644 --- a/bind/gen_type.go +++ b/bind/gen_type.go @@ -34,31 +34,37 @@ func (g *pybindGen) genType(sym *symbol) { } func (g *pybindGen) genTypeHandlePtr(sym *symbol) { - g.gofile.Printf("\n// Converters for pointer handles for type: %s\n", sym.gofmt()) - g.gofile.Printf("func %s(h CGoHandle) %s {\n", sym.py2go, sym.gofmt()) + gonm := sym.gofmt() + g.gofile.Printf("\n// Converters for pointer handles for type: %s\n", gonm) + g.gofile.Printf("func %s(h CGoHandle) %s {\n", sym.py2go, gonm) g.gofile.Indent() - g.gofile.Printf("p := gopyh.VarHand.VarFmHandle((gopyh.CGoHandle)(h), %[1]q)\n", sym.gofmt()) + g.gofile.Printf("p := gopyh.VarHand.VarFmHandle((gopyh.CGoHandle)(h), %[1]q)\n", gonm) g.gofile.Printf("if p == nil {\n") g.gofile.Indent() g.gofile.Printf("return nil\n") g.gofile.Outdent() g.gofile.Printf("}\n") - g.gofile.Printf("return p.(%[1]s)\n", sym.gofmt()) + g.gofile.Printf("return p.(%[1]s)\n", gonm) g.gofile.Outdent() g.gofile.Printf("}\n") g.gofile.Printf("func %s(p interface{}) CGoHandle {\n", sym.go2py) g.gofile.Indent() - g.gofile.Printf("return CGoHandle(gopyh.VarHand.Register(\"%s\", p))\n", sym.gofmt()) + g.gofile.Printf("return CGoHandle(gopyh.VarHand.Register(\"%s\", p))\n", gonm) g.gofile.Outdent() g.gofile.Printf("}\n") } func (g *pybindGen) genTypeHandle(sym *symbol) { - ptrnm := "*" + sym.gofmt() - g.gofile.Printf("\n// Converters for non-pointer handles for type: %s\n", sym.gofmt()) - g.gofile.Printf("func %s(h CGoHandle) %s {\n", sym.py2go, ptrnm) + gonm := sym.gofmt() + ptrnm := "*" + gonm + py2go := sym.py2go + if py2go[0] == '*' { + py2go = py2go[1:] + } + g.gofile.Printf("\n// Converters for non-pointer handles for type: %s\n", gonm) + g.gofile.Printf("func %s(h CGoHandle) %s {\n", py2go, ptrnm) g.gofile.Indent() - g.gofile.Printf("p := gopyh.VarHand.VarFmHandle((gopyh.CGoHandle)(h), %[1]q)\n", sym.gofmt()) + g.gofile.Printf("p := gopyh.VarHand.VarFmHandle((gopyh.CGoHandle)(h), %[1]q)\n", gonm) g.gofile.Printf("if p == nil {\n") g.gofile.Indent() g.gofile.Printf("return nil\n") @@ -69,7 +75,7 @@ func (g *pybindGen) genTypeHandle(sym *symbol) { g.gofile.Printf("}\n") g.gofile.Printf("func %s(p interface{}) CGoHandle {\n", sym.go2py) g.gofile.Indent() - g.gofile.Printf("return CGoHandle(gopyh.VarHand.Register(\"%s\", p))\n", sym.gofmt()) + g.gofile.Printf("return CGoHandle(gopyh.VarHand.Register(\"%s\", p))\n", gonm) g.gofile.Outdent() g.gofile.Printf("}\n") } diff --git a/bind/gen_varconst.go b/bind/gen_varconst.go index 187b879..8f652e7 100644 --- a/bind/gen_varconst.go +++ b/bind/gen_varconst.go @@ -70,9 +70,9 @@ func (g *pybindGen) genVarSetter(v Var) { g.gofile.Indent() if v.sym.go2py != "" { if v.sym.hasHandle() && !v.sym.isPtrOrIface() { - g.gofile.Printf("%s = *%s(val)", qVn, v.sym.py2go) + g.gofile.Printf("%s = *%s(val)%s", qVn, v.sym.py2go, v.sym.py2goParenEx) } else { - g.gofile.Printf("%s = %s(val)", qVn, v.sym.py2go) + g.gofile.Printf("%s = %s(val)%s", qVn, v.sym.py2go, v.sym.py2goParenEx) } } else { g.gofile.Printf("%s = val", qVn) diff --git a/bind/package.go b/bind/package.go index 618ae2c..1721497 100644 --- a/bind/package.go +++ b/bind/package.go @@ -86,6 +86,11 @@ func (p *Package) getDoc(parent string, o types.Object) string { } case *types.Func: + sig := o.Type().(*types.Signature) + err, _, _ := isPyCompatFunc(sig) + if err != nil { + return "" + } doc := func() string { if o.Parent() == nil || (o.Parent() != nil && parent != "") { for _, typ := range p.doc.Types { @@ -116,8 +121,6 @@ func (p *Package) getDoc(parent string, o types.Object) string { return "" }() - sig := o.Type().(*types.Signature) - parseFn := func(tup *types.Tuple) []string { params := []string{} if tup == nil { @@ -318,10 +321,7 @@ func (p *Package) process() error { mname := types.ObjectString(m, nil) msym := p.syms.sym(mname) if msym == nil { - panic(fmt.Errorf( - "gopy: could not retrieve symbol for %q", - m.FullName(), - )) + continue } msym.doc = doc } diff --git a/bind/symbols.go b/bind/symbols.go index 09de532..e7f76a2 100644 --- a/bind/symbols.go +++ b/bind/symbols.go @@ -77,39 +77,40 @@ func (k symkind) String() string { // symbol is an exported symbol in a go package type symbol struct { - kind symkind - gopkg *types.Package - goobj types.Object - gotyp types.Type - doc string - id string // mangled name of entity (eg: _) - goname string // name of go entity - pyname string // name of python entity (nonptrname, cleaned-up slice name) - cgoname string // type name of entity for cgo -- handle for objs - cpyname string // type name of entity for cgo - python -- handle.. - pysig string // type string for doc-signatures - go2py string // name of go->py converter function - py2go string // name of py->go converter function - zval string // zero value representation + kind symkind + gopkg *types.Package + goobj types.Object + gotyp types.Type + doc string + id string // mangled name of entity (eg: _) + goname string // name of go entity + pyname string // name of python entity (nonptrname, cleaned-up slice name) + cgoname string // type name of entity for cgo -- handle for objs + cpyname string // type name of entity for cgo - python -- handle.. + pysig string // type string for doc-signatures + go2py string // name of go->py converter function + py2go string // name of py->go converter function + py2goParenEx string // extra parentheses needed at end of py2go (beyond 1 default) + zval string // zero value representation } func isPrivate(s string) bool { return (strings.ToLower(s[0:1]) == s[0:1]) } -func (s symbol) isType() bool { +func (s *symbol) isType() bool { return (s.kind & skType) != 0 } -func (s symbol) isNamed() bool { +func (s *symbol) isNamed() bool { return (s.kind & skNamed) != 0 } -func (s symbol) isBasic() bool { +func (s *symbol) isBasic() bool { return (s.kind & skBasic) != 0 } -func (s symbol) isNamedBasic() bool { +func (s *symbol) isNamedBasic() bool { if !s.isNamed() { return false } @@ -120,65 +121,65 @@ func (s symbol) isNamedBasic() bool { return false } -func (s symbol) isArray() bool { +func (s *symbol) isArray() bool { return (s.kind & skArray) != 0 } -func (s symbol) isInterface() bool { +func (s *symbol) isInterface() bool { return (s.kind & skInterface) != 0 } -func (s symbol) isSignature() bool { +func (s *symbol) isSignature() bool { return (s.kind & skSignature) != 0 } -func (s symbol) isMap() bool { +func (s *symbol) isMap() bool { return (s.kind & skMap) != 0 } -func (s symbol) isPySequence() bool { +func (s *symbol) isPySequence() bool { return s.isArray() || s.isSlice() || s.isMap() } -func (s symbol) isSlice() bool { +func (s *symbol) isSlice() bool { return (s.kind & skSlice) != 0 } -func (s symbol) isStruct() bool { +func (s *symbol) isStruct() bool { return (s.kind & skStruct) != 0 } -func (s symbol) isPointer() bool { +func (s *symbol) isPointer() bool { return (s.kind & skPointer) != 0 } -func (s symbol) isPtrOrIface() bool { +func (s *symbol) isPtrOrIface() bool { return s.isPointer() || s.isInterface() } -func (s symbol) hasHandle() bool { +func (s *symbol) hasHandle() bool { return !s.isBasic() } -func (s symbol) hasConverter() bool { +func (s *symbol) hasConverter() bool { return (s.go2py != "" || s.py2go != "") } -func (s symbol) pkgname() string { +func (s *symbol) pkgname() string { if s.gopkg == nil { return "" } return s.gopkg.Name() } -func (s symbol) GoType() types.Type { +func (s *symbol) GoType() types.Type { if s.goobj != nil { return s.goobj.Type() } return s.gotyp } -func (s symbol) cgotypename() string { +func (s *symbol) cgotypename() string { typ := s.gotyp switch typ := typ.(type) { case *types.Basic: @@ -201,11 +202,10 @@ func (s symbol) cgotypename() string { return s.cgoname } -func (s symbol) gofmt() string { +func (s *symbol) gofmt() string { return types.TypeString( s.GoType(), - func(*types.Package) string { return s.pkgname() }, - ) + func(pkg *types.Package) string { return pkg.Name() }) } // symtab is a table of symbols in a go package @@ -314,20 +314,22 @@ func (sym *symtab) addSymbol(obj types.Object) { sym.addType(obj, obj.Type()) case *types.Func: - sym.syms[fn] = &symbol{ - gopkg: pkg, - goobj: obj, - kind: skFunc, - id: id, - goname: n, - pyname: pyname, - cgoname: n, - cpyname: n, - } sig := obj.Type().Underlying().(*types.Signature) - sym.processTuple(sig.Params()) - sym.processTuple(sig.Results()) - + err, _, _ := isPyCompatFunc(sig) + if err == nil { + sym.syms[fn] = &symbol{ + gopkg: pkg, + goobj: obj, + kind: skFunc, + id: id, + goname: n, + pyname: pyname, + cgoname: n, + cpyname: n, + } + sym.processTuple(sig.Params()) + sym.processTuple(sig.Results()) + } case *types.TypeName: sym.addType(obj, obj.Type()) @@ -350,16 +352,46 @@ func (sym *symtab) processTuple(tuple *types.Tuple) { } } -// typePackage gets the package for a given types.Type -func typePackage(t types.Type) *types.Package { - if tn, ok := t.(*types.Named); ok { - return tn.Obj().Pkg() +// isPyCompatFunc checks if function signature is a python-compatible function. +// Returns nil if function is compatible, err message if not. +// Also returns the return type of the function +// extra bool is true if 2nd arg is an error type, which is only +// supported form of multi-return-value functions +func isPyCompatFunc(sig *types.Signature) (error, types.Type, bool) { + haserr := false + res := sig.Results() + var ret types.Type + + switch res.Len() { + case 2: + if !isErrorType(res.At(1).Type()) { + return fmt.Errorf("gopy: second result value must be of type error: %s", sig.String()), ret, haserr + } + haserr = true + ret = res.At(0).Type() + case 1: + if isErrorType(res.At(0).Type()) { + haserr = true + ret = nil + } else { + ret = res.At(0).Type() + } + case 0: + ret = nil + default: + return fmt.Errorf("gopy: too many results to return: %s", sig.String()), ret, haserr } - switch tt := t.(type) { - case *types.Pointer: - return typePackage(tt.Elem()) + + args := sig.Params() + nargs := args.Len() + for i := 0; i < nargs; i++ { + arg := args.At(i) + argt := arg.Type() + if _, isSig := argt.(*types.Signature); isSig { + return fmt.Errorf("gopy: func args (signature) not supported: %s", sig.String()), ret, haserr + } } - return nil + return nil, ret, haserr } // goToPyName translates a go type name to a safe python-usable @@ -371,21 +403,35 @@ func goToPyName(gon string) string { return pyn } -func (sym *symtab) addType(obj types.Object, t types.Type) { - fn := sym.typename(t, nil) +// typePkg gets the package for a given types.Type +func typePkg(t types.Type) *types.Package { + if tn, ok := t.(*types.Named); ok { + return tn.Obj().Pkg() + } + switch tt := t.(type) { + case *types.Pointer: + return typePkg(tt.Elem()) + } + return nil +} + +// typeNamePkg gets the name and package for a given types.Type -- deals with +// naming for types in other packages, and adds those packages to imports paths. +// Falls back on sym.pkg if no other package info avail. +func (sym *symtab) typeNamePkg(t types.Type) (string, *types.Package) { n := sym.typename(t, sym.pkg) var pkg *types.Package if lidx := strings.LastIndex(n, "/"); lidx > 0 { qnm := n[lidx+1:] n = strings.Replace(qnm, ".", "_", 1) - pkg = typePackage(t) + pkg = typePkg(t) if pkg != nil { ip := pkg.Path() sym.imports[ip] = ip } } else if pidx := strings.LastIndex(n, "."); pidx > 0 { n = strings.Replace(n, ".", "_", 1) - pkg = typePackage(t) + pkg = typePkg(t) if pkg != nil { ip := pkg.Path() sym.imports[ip] = ip @@ -394,6 +440,12 @@ func (sym *symtab) addType(obj types.Object, t types.Type) { if pkg == nil { pkg = sym.pkg } + return n, pkg +} + +func (sym *symtab) addType(obj types.Object, t types.Type) { + fn := sym.typename(t, nil) + n, pkg := sym.typeNamePkg(t) id := n if pkg != nil { id = pkg.Name() + "_" + n @@ -407,6 +459,9 @@ func (sym *symtab) addType(obj types.Object, t types.Type) { panic(fmt.Errorf("builtin type not already known [%s]!", n)) } + case *types.Pointer: + sym.addPointerType(pkg, obj, t, kind, id, n) + case *types.Array: sym.addArrayType(pkg, obj, t, kind, id, n) @@ -424,19 +479,28 @@ func (sym *symtab) addType(obj types.Object, t types.Type) { case *types.Basic: styp := sym.symtype(st) + py2go := pkg.Name() + "." + sym.typename(t, pkg) + py2goParEx := "" + if styp.py2go != "" { + py2go += "(" + styp.py2go + py2goParEx = ")" + } + sym.syms[fn] = &symbol{ - gopkg: pkg, - goobj: obj, - gotyp: t, - kind: kind | skBasic, - id: id, - goname: styp.goname, - pyname: styp.pyname, - cgoname: styp.cgoname, - cpyname: styp.cpyname, - pysig: styp.pysig, - go2py: styp.cgoname, - py2go: pkg.Name() + "." + n, + gopkg: pkg, + goobj: obj, + gotyp: t, + kind: kind | skBasic, + id: id, + goname: styp.goname, + pyname: styp.pyname, + cgoname: styp.cgoname, + cpyname: styp.cpyname, + pysig: styp.pysig, + go2py: styp.cgoname, + py2go: py2go, + py2goParenEx: py2goParEx, + zval: styp.zval, } case *types.Array: @@ -471,9 +535,6 @@ func (sym *symtab) addType(obj types.Object, t types.Type) { } } - case *types.Pointer: - sym.addPointerType(pkg, obj, t, kind, id, n) - case *types.Map: sym.addMapType(pkg, obj, t, kind, id, n) @@ -491,10 +552,13 @@ func (sym *symtab) addArrayType(pkg *types.Package, obj types.Object, t types.Ty if elt == nil || elt.goname == "" { eltname := sym.typename(typ.Elem(), pkg) eobj := sym.pkg.Scope().Lookup(eltname) - if eobj == nil { - panic(fmt.Errorf("could not look-up %q!\n", enam)) + if eobj != nil { + sym.addSymbol(eobj) + } else { + if ntyp, ok := typ.Elem().(*types.Named); ok { + sym.addType(ntyp.Obj(), typ.Elem()) + } } - sym.addSymbol(eobj) elt = sym.sym(enam) if elt == nil { panic(fmt.Errorf( @@ -528,21 +592,22 @@ func (sym *symtab) addMapType(pkg *types.Package, obj types.Object, t types.Type fn := sym.typename(t, nil) typ := t.Underlying().(*types.Map) kind |= skMap - enam := sym.typename(typ.Elem(), nil) - elt := sym.sym(enam) - if elt == nil || elt.goname == "" { - eltname := sym.typename(typ.Elem(), pkg) + elt := typ.Elem() + enam := sym.typename(elt, nil) + elsym := sym.sym(enam) + if elsym == nil || elsym.goname == "" { + eltname, _ := sym.typeNamePkg(elt) eobj := sym.pkg.Scope().Lookup(eltname) - if eobj == nil { - panic(fmt.Errorf("could not look-up %q!\n", enam)) + if eobj != nil { + sym.addSymbol(eobj) + } else { + if ntyp, ok := elt.(*types.Named); ok { + sym.addType(ntyp.Obj(), elt) + } } - sym.addSymbol(eobj) - elt = sym.sym(enam) - if elt == nil { - panic(fmt.Errorf( - "gopy: could not retrieve map-elt symbol for %q", - enam, - )) + elsym = sym.sym(enam) + if elsym == nil { + panic(fmt.Errorf("gopy: map key type must be named type if outside current package: %q", enam)) } } pyname := n @@ -570,22 +635,24 @@ func (sym *symtab) addSliceType(pkg *types.Package, obj types.Object, t types.Ty fn := sym.typename(t, nil) typ := t.Underlying().(*types.Slice) kind |= skSlice - enam := sym.typename(typ.Elem(), nil) - elt := sym.sym(enam) - if elt == nil || elt.goname == "" { - eltname := sym.typename(typ.Elem(), pkg) + elt := typ.Elem() + enam := sym.typename(elt, nil) + elsym := sym.sym(enam) + if elsym == nil || elsym.goname == "" { + eltname, _ := sym.typeNamePkg(elt) eobj := sym.pkg.Scope().Lookup(eltname) - if eobj == nil { - panic(fmt.Errorf("could not look-up %q!\n", enam)) + if eobj != nil { + sym.addSymbol(eobj) + } else { + if ntyp, ok := elt.(*types.Named); ok { + sym.addType(ntyp.Obj(), elt) + } } - sym.addSymbol(eobj) - elt = sym.sym(enam) - if elt == nil { - panic(fmt.Errorf( - "gopy: could not retrieve slice-elt symbol for %q", - enam, - )) + elsym = sym.sym(enam) + if elsym == nil { + panic(fmt.Errorf("gopy: slice type must be named type if outside current package: %q", enam)) } + n = "[]" + elsym.goname } pyname := goToPyName(n) sym.syms[fn] = &symbol{ @@ -598,7 +665,7 @@ func (sym *symtab) addSliceType(pkg *types.Package, obj types.Object, t types.Ty pyname: pyname, cgoname: "CGoHandle", cpyname: PyHandle, - pysig: "[]" + elt.pysig, + pysig: "[]" + elsym.pysig, go2py: "handleFmPtr_" + pyname, py2go: "ptrFmHandle_" + pyname, zval: "nil", @@ -638,7 +705,7 @@ func (sym *symtab) addStructType(pkg *types.Package, obj types.Object, t types.T cpyname: PyHandle, pysig: "object", go2py: "handleFmPtr_" + n, - py2go: "ptrFmHandle_" + n, + py2go: "*ptrFmHandle_" + n, } } @@ -666,22 +733,25 @@ func (sym *symtab) addSignatureType(pkg *types.Package, obj types.Object, t type } func (sym *symtab) addMethod(pkg *types.Package, obj types.Object, t types.Type, kind symkind, id, n string) { - fn := types.ObjectString(obj, nil) - kind |= skFunc - sym.syms[fn] = &symbol{ - gopkg: pkg, - goobj: obj, - gotyp: t, - kind: kind, - id: id, - goname: n, - pyname: n, - cgoname: fn + "_" + n, - cpyname: fn + "_" + n, - } sig := t.Underlying().(*types.Signature) - sym.processTuple(sig.Results()) - sym.processTuple(sig.Params()) + err, _, _ := isPyCompatFunc(sig) + if err == nil { + fn := types.ObjectString(obj, nil) + kind |= skFunc + sym.syms[fn] = &symbol{ + gopkg: pkg, + goobj: obj, + gotyp: t, + kind: kind, + id: id, + goname: n, + pyname: n, + cgoname: fn + "_" + n, + cpyname: fn + "_" + n, + } + sym.processTuple(sig.Results()) + sym.processTuple(sig.Params()) + } } func (sym *symtab) addPointerType(pkg *types.Package, obj types.Object, t types.Type, kind symkind, id, n string) { @@ -1022,7 +1092,7 @@ func init() { kind: skType | skBasic, goname: "rune", pyname: "str", - cpyname: "GoRune", + cpyname: "int32_t", cgoname: "C.long", pysig: "str", go2py: "C.long", diff --git a/bind/types.go b/bind/types.go index e0d7500..aec0d5b 100644 --- a/bind/types.go +++ b/bind/types.go @@ -229,42 +229,9 @@ type Func struct { } func newFuncFrom(p *Package, parent string, obj types.Object, sig *types.Signature) (Func, error) { - haserr := false - res := sig.Results() - var ret types.Type - - switch res.Len() { - case 2: - if !isErrorType(res.At(1).Type()) { - return Func{}, fmt.Errorf( - "bind: second result value must be of type error: %s", - obj, - ) - } - haserr = true - ret = res.At(0).Type() - - case 1: - if isErrorType(res.At(0).Type()) { - haserr = true - ret = nil - } else { - ret = res.At(0).Type() - } - case 0: - ret = nil - default: - return Func{}, fmt.Errorf("bind: too many results to return: %v", obj) - } - - args := sig.Params() - nargs := args.Len() - for i := 0; i < nargs; i++ { - arg := args.At(i) - argt := arg.Type() - if _, isSig := argt.(*types.Signature); isSig { - return Func{}, fmt.Errorf("bind: func args (signature) not supported: %v", obj) - } + err, ret, haserr := isPyCompatFunc(sig) + if err != nil { + return Func{}, err } id := obj.Pkg().Name() + "_" + obj.Name() diff --git a/gen/test.py b/gen/test.py deleted file mode 100644 index daa80cb..0000000 --- a/gen/test.py +++ /dev/null @@ -1,276 +0,0 @@ -# Copyright 2015 The go-python Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -from __future__ import print_function - -import hi - -print("--- doc(hi)...") -print(hi.__doc__) - -print("--- hi.Universe:", hi.Universe) -print("--- hi.Version:", hi.Version) - -print("--- hi.Debug():",hi.Debug()) -print("--- hi.SetDebug(true)") -hi.SetDebug(True) -print("--- hi.Debug():",hi.Debug()) -print("--- hi.SetDebug(false)") -hi.SetDebug(False) -print("--- hi.Debug():",hi.Debug()) - -print("--- hi.Anon():",hi.Anon()) -anon = hi.NewPerson('you',24) -print("--- new anon:",anon) -print("--- hi.SetAnon(hi.NewPerson('you', 24))...") -hi.SetAnon(anon) -print("--- hi.Anon():",hi.Anon()) - -print("--- doc(hi.Hi)...") -print(hi.Hi.__doc__) - -print("--- hi.Hi()...") -hi.Hi() - -print("--- doc(hi.Hello)...") -print(hi.Hello.__doc__) - -print("--- hi.Hello('you')...") -hi.Hello("you") - -print("--- doc(hi.Add)...") -print(hi.Add.__doc__) - -print("--- hi.Add(1, 41)...") -print(hi.Add(1,41)) - -print("--- hi.Concat('4', '2')...") -print(hi.Concat("4","2")) - -print("--- hi.LookupQuestion(42)...") -print(hi.LookupQuestion(42)) - -print("--- hi.LookupQuestion(12)...") -try: - hi.LookupQuestion(12) - print("*ERROR* no exception raised!") -except Exception as err: - print("caught:", err) - pass - -print("--- doc(hi.Person):") -print(hi.Person.__doc__) - -print("--- p = hi.Person()...") -p = hi.Person() -print("--- p:", p) - -print("--- p.Name:", p.Name) -print("--- p.Age:",p.Age) - -print("--- doc(hi.Greet):") -print(p.Greet.__doc__) -print("--- p.Greet()...") -print(p.Greet()) - -print("--- p.String()...") -print(p.String()) - -print("--- doc(p):") -print(p.__doc__) - -print("--- p.Name = \"foo\"...") -p.Name = "foo" - -print("--- p.Age = 42...") -p.Age = 42 - -print("--- p.String()...") -print(p.String()) -print("--- p.Age:", p.Age) -print("--- p.Name:",p.Name) - -print("--- p.Work(2)...") -p.Work(2) - -print("--- p.Work(24)...") -try: - p.Work(24) - print("*ERROR* no exception raised!") -except Exception as err: - print("caught:", err) - pass - -print("--- p.Salary(2):", p.Salary(2)) -try: - print("--- p.Salary(24):",p.Salary(24)) - print("*ERROR* no exception raised!") -except Exception as err: - print("--- p.Salary(24): caught:", err) - pass - -## test ctor args -print("--- Person.__init__") -try: - hi.Person(1) - print("*ERROR* no exception raised!") -except Exception as err: - print("caught:", err, "| err-type:",type(err)) - pass - -try: - hi.Person("name","2") - print("*ERROR* no exception raised!") -except Exception as err: - print("caught:", err, "| err-type:",type(err)) - pass - -try: - hi.Person("name",2,3) - print("*ERROR* no exception raised!") -except Exception as err: - print("caught:", err, "| err-type:",type(err)) - pass - -p = hi.Person("name") -print(p) -p = hi.Person("name", 42) -print(p) -p = hi.Person(Name="name", Age=42) -print(p) -p = hi.Person(Age=42, Name="name") -print(p) - -## test ctors -print("--- hi.NewPerson('me', 666):", hi.NewPerson("me", 666)) -print("--- hi.NewPersonWithAge(666):", hi.NewPersonWithAge(666)) -print("--- hi.NewActivePerson(4):") -p = hi.NewActivePerson(4) -print(p) - -## test cross-package -# todo: need to be able to import multiple packages -#s2 = p.ReturnS2Ptr() -#print("s2: ", s2) - -## test interface -pif = hi.PersonAsIface("me", 666) -print("--- hi.PersonAsIface('me', 666):", pif) -print("--- pif.GetName():", pif.GetName()) -print("--- pif.GetAge():", pif.GetAge()) -print("--- pif.SetAge(22):", pif.SetAge(22)) -print("--- pif.GetAge():", pif.GetAge()) - -# test Couple -print("--- c = hi.Couple()...") -c = hi.Couple() -print(c) -print("--- c.P1:", c.P1) -c.P1 = hi.NewPerson("tom", 5) -c.P2 = hi.NewPerson("bob", 2) -print("--- c:", c) - -print("--- c = hi.NewCouple(tom, bob)...") -c = hi.NewCouple(hi.NewPerson("tom", 50), hi.NewPerson("bob", 41)) -print(c.String()) -c.P1.Name = "mom" -c.P2.Age = 51 -print(c.String()) - -# test Couple.__init__ -print("--- Couple.__init__") -#c = hi.NewCouple(hi.NewPerson("p1", 42)) -#print(c) -c = hi.NewCouple(hi.NewPerson("p1", 42), hi.NewPerson("p2", 52)) -print(c.String()) -# note: not supporting named args -- not worth it for now! -#c = hi.NewCouple(P1=hi.NewPerson("p1", 42), P2=hi.NewPerson("p2", 52)) -#print(c) -#c = hi.NewCouple(P2=hi.NewPerson("p1", 42), P1=hi.NewPerson("p2", 52)) -#print(c) - -try: - hi.Couple(1) - print("*ERROR* no exception raised!") -except Exception as err: - print("caught:", err, "| err-type:",type(err)) - pass - -try: - hi.Couple(1,2) - print("*ERROR* no exception raised!") -except Exception as err: - print("caught:", err, "| err-type:",type(err)) - pass - -try: - hi.Couple(P2=1) - print("*ERROR* no exception raised!") -except Exception as err: - print("caught:", err, "| err-type:",type(err)) - pass - -### test gc -print("--- testing GC...") -#NMAX = 100000 -NMAX = 10 -objs = [] -for i in range(NMAX): - p1 = hi.NewPerson("p1-%d" % i, i) - p2 = hi.NewPerson("p2-%d" % i, i) - objs.append(hi.NewCouple(p1,p2)) - pass -print("--- len(objs):",len(objs)) -vs = [] -for i,o in enumerate(objs): - v = "%d: %s" % (i, o) - vs.append(v) - pass -print("--- len(vs):",len(vs)) -del objs -print("--- testing GC... [ok]") - -print("--- testing slice...") -s = hi.IntSlice() -print("slice:",s) -print("len(slice):",len(s)) -print("slice[0]:",s[0]) -print("slice[1]:",s[1]) -try: - print("slice[2]:", s[2]) - print("*ERROR* no exception raised!") -except Exception as err: - print("slice[2]: caught:",err) - pass -s[1] = 42 -print("slice:",s) -print("len(slice):",len(s)) -try: - print("mem(slice):",len(memoryview(s))) -except Exception as err: - print("mem(slice): caught:",err) - pass - -print("--- testing array...") -arr = hi.IntArray() -print("arr:",arr) -print("len(arr):",len(arr)) -print("arr[0]:",arr[0]) -print("arr[1]:",arr[1]) -try: - print("arr[2]:", arr[2]) - print("*ERROR* no exception raised!") -except Exception as err: - print("arr[2]: caught:",err) - pass -arr[1] = 42 -print("arr:",arr) -print("len(arr):",len(arr)) -try: - print("mem(arr):",len(memoryview(arr))) -except Exception as err: - print("mem(arr): caught:",err) - pass - -print("OK")