mirror of https://github.com/go-python/gopy.git
220 lines
6.1 KiB
Go
220 lines
6.1 KiB
Go
// Copyright 2019 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.
|
|
|
|
package bind
|
|
|
|
// extTypes = these are types external to any targeted packages
|
|
// pyWrapOnly = only generate python wrapper code, not go code
|
|
func (g *pyGen) genType(sym *symbol, extTypes, pyWrapOnly bool) {
|
|
if !sym.isType() {
|
|
return
|
|
}
|
|
if sym.isBasic() && !sym.isNamed() {
|
|
return
|
|
}
|
|
|
|
if sym.isNamedBasic() {
|
|
// TODO: could have methods!
|
|
return
|
|
}
|
|
|
|
// TODO: not handling yet:
|
|
if sym.isSignature() {
|
|
return
|
|
}
|
|
|
|
if !pyWrapOnly {
|
|
switch {
|
|
case sym.isPointer() || sym.isInterface():
|
|
g.genTypeHandlePtr(sym)
|
|
case sym.isSlice() || sym.isMap() || sym.isArray():
|
|
g.genTypeHandleImplPtr(sym)
|
|
default:
|
|
g.genTypeHandle(sym)
|
|
}
|
|
}
|
|
|
|
if extTypes {
|
|
if sym.isSlice() || sym.isArray() {
|
|
g.genSlice(sym, extTypes, pyWrapOnly, nil)
|
|
} else if sym.isMap() {
|
|
g.genMap(sym, extTypes, pyWrapOnly, nil)
|
|
} else if sym.isInterface() || sym.isStruct() {
|
|
if pyWrapOnly {
|
|
g.genExtClass(sym)
|
|
}
|
|
}
|
|
} else {
|
|
if g.pkg == goPackage || !sym.isNamed() { // only named types are generated separately
|
|
if sym.isSlice() {
|
|
g.genSlice(sym, extTypes, pyWrapOnly, nil)
|
|
} else if sym.isMap() {
|
|
g.genMap(sym, extTypes, pyWrapOnly, nil)
|
|
}
|
|
}
|
|
if sym.isArray() {
|
|
g.genSlice(sym, extTypes, pyWrapOnly, nil)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (g *pyGen) genTypeHandlePtr(sym *symbol) {
|
|
if sym.goname == "interface{}" {
|
|
return
|
|
}
|
|
gonm := sym.goname
|
|
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.VarFromHandle((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")
|
|
if sym.isStruct() {
|
|
g.gofile.Printf("return gopyh.Embed(p, reflect.TypeOf(%s{})).(%s)\n", nonPtrName(gonm), gonm)
|
|
} else {
|
|
g.gofile.Printf("return p.(%s)\n", gonm)
|
|
}
|
|
g.gofile.Outdent()
|
|
g.gofile.Printf("}\n")
|
|
g.gofile.Printf("func %s(p interface{})%s CGoHandle {\n", sym.go2py, sym.go2pyParenEx)
|
|
g.gofile.Indent()
|
|
g.gofile.Printf("return CGoHandle(gopyh.Register(\"%s\", p))\n", gonm)
|
|
g.gofile.Outdent()
|
|
g.gofile.Printf("}\n")
|
|
}
|
|
|
|
// implicit pointer types: slice, map, array
|
|
func (g *pyGen) genTypeHandleImplPtr(sym *symbol) {
|
|
gonm := sym.goname
|
|
ptrnm := gonm
|
|
nptrnm := gonm
|
|
if ptrnm[0] != '*' {
|
|
ptrnm = "*" + ptrnm
|
|
} else {
|
|
nptrnm = gonm[1:]
|
|
}
|
|
g.gofile.Printf("\n// Converters for implicit pointer handles for type: %s\n", gonm)
|
|
g.gofile.Printf("func ptrFromHandle_%s(h CGoHandle) %s {\n", sym.id, ptrnm)
|
|
g.gofile.Indent()
|
|
g.gofile.Printf("p := gopyh.VarFromHandle((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.(%s)\n", ptrnm)
|
|
g.gofile.Outdent()
|
|
g.gofile.Printf("}\n")
|
|
g.gofile.Printf("func deptrFromHandle_%s(h CGoHandle) %s {\n", sym.id, nptrnm)
|
|
g.gofile.Indent()
|
|
g.gofile.Printf("p := ptrFromHandle_%s(h)\n", sym.id)
|
|
if !sym.isArray() {
|
|
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\n")
|
|
g.gofile.Outdent()
|
|
g.gofile.Printf("}\n")
|
|
g.gofile.Printf("func %s(p interface{})%s CGoHandle {\n", sym.go2py, sym.go2pyParenEx)
|
|
g.gofile.Indent()
|
|
g.gofile.Printf("return CGoHandle(gopyh.Register(\"%s\", p))\n", gonm)
|
|
g.gofile.Outdent()
|
|
g.gofile.Printf("}\n")
|
|
}
|
|
|
|
func nonPtrName(nm string) string {
|
|
if nm[0] == '*' {
|
|
return nm[1:]
|
|
}
|
|
return nm
|
|
}
|
|
|
|
func (g *pyGen) genTypeHandle(sym *symbol) {
|
|
gonm := sym.goname
|
|
ptrnm := gonm
|
|
if ptrnm[0] != '*' {
|
|
ptrnm = "*" + ptrnm
|
|
}
|
|
py2go := nonPtrName(sym.py2go)
|
|
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.VarFromHandle((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")
|
|
if sym.isStruct() {
|
|
g.gofile.Printf("return gopyh.Embed(p, reflect.TypeOf(%s{})).(%s)\n", nonPtrName(gonm), ptrnm)
|
|
} else {
|
|
g.gofile.Printf("return p.(%s)\n", ptrnm)
|
|
}
|
|
g.gofile.Outdent()
|
|
g.gofile.Printf("}\n")
|
|
g.gofile.Printf("func %s(p interface{})%s CGoHandle {\n", sym.go2py, sym.go2pyParenEx)
|
|
g.gofile.Indent()
|
|
g.gofile.Printf("return CGoHandle(gopyh.Register(\"%s\", p))\n", gonm)
|
|
g.gofile.Outdent()
|
|
g.gofile.Printf("}\n")
|
|
}
|
|
|
|
// genExtClass generates minimal python wrappers for external classes (struct, interface, etc)
|
|
func (g *pyGen) genExtClass(sym *symbol) {
|
|
pkgname := sym.gopkg.Name()
|
|
// note: all external wrapper classes are defined in base go.py module, so we exclude go.
|
|
g.pywrap.Printf(`
|
|
# Python type for %[4]s
|
|
class %[2]s(GoClass):
|
|
""%[3]q""
|
|
`,
|
|
pkgname,
|
|
sym.id,
|
|
sym.doc,
|
|
sym.goname,
|
|
)
|
|
g.pywrap.Indent()
|
|
g.pywrap.Printf("def __init__(self, *args, **kwargs):\n")
|
|
g.pywrap.Indent()
|
|
g.pywrap.Printf(`"""
|
|
handle=A Go-side object is always initialized with an explicit handle=arg
|
|
"""
|
|
`)
|
|
g.pywrap.Printf("if len(kwargs) == 1 and 'handle' in kwargs:\n")
|
|
g.pywrap.Indent()
|
|
g.pywrap.Printf("self.handle = kwargs['handle']\n")
|
|
g.pywrap.Printf("_%s.IncRef(self.handle)\n", g.pypkgname)
|
|
g.pywrap.Outdent()
|
|
g.pywrap.Printf("elif len(args) == 1 and isinstance(args[0], GoClass):\n")
|
|
g.pywrap.Indent()
|
|
g.pywrap.Printf("self.handle = args[0].handle\n")
|
|
g.pywrap.Printf("_%s.IncRef(self.handle)\n", g.pypkgname)
|
|
g.pywrap.Outdent()
|
|
g.pywrap.Printf("elif len(args) == 1 and isinstance(args[0], int):\n")
|
|
g.pywrap.Indent()
|
|
g.pywrap.Printf("self.handle = args[0]\n")
|
|
g.pywrap.Printf("_%s.IncRef(self.handle)\n", g.pypkgname)
|
|
g.pywrap.Outdent()
|
|
g.pywrap.Printf("else:\n")
|
|
g.pywrap.Indent()
|
|
g.pywrap.Printf("self.handle = 0\n")
|
|
g.pywrap.Outdent()
|
|
g.pywrap.Outdent()
|
|
|
|
g.pywrap.Printf("def __del__(self):\n")
|
|
g.pywrap.Indent()
|
|
g.pywrap.Printf("_%s.DecRef(self.handle)\n", g.pypkgname)
|
|
g.pywrap.Outdent()
|
|
|
|
g.pywrap.Printf("\n")
|
|
g.pywrap.Outdent()
|
|
|
|
}
|