mirror of https://github.com/go-python/gopy.git
cffi: Support named type + Pass 'seq.go' test.
* Pass 'named.go' test. * Support to generate named type includes slice and array types. * Add doc.go for bind package. * Add comments. * Support __iadd__ for Go slice types. * Add a 'seq.go' test for the CFFI engine.
This commit is contained in:
parent
3b8a754b6c
commit
c2676d7f14
|
@ -6,6 +6,9 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import named
|
||||
import sys
|
||||
|
||||
_PY2 = sys.version_info[0] == 2
|
||||
|
||||
### test docs
|
||||
print("doc(named): %r" % (named.__doc__,))
|
||||
|
@ -96,13 +99,14 @@ try:
|
|||
print("arr = named.Array(range(10))")
|
||||
arr = named.Array(range(10))
|
||||
print("arr = %s" % (arr,))
|
||||
except Exception, err:
|
||||
print("caught: %s" % (err,))
|
||||
except Exception as err:
|
||||
print("caught: %s" % (str(err),))
|
||||
pass
|
||||
|
||||
print("arr = named.Array(xrange(2))")
|
||||
arr = named.Array(xrange(2))
|
||||
print("arr = %s" % (arr,))
|
||||
if _PY2:
|
||||
print("arr = named.Array(xrange(2))")
|
||||
arr = named.Array(xrange(2))
|
||||
print("arr = %s" % (arr,))
|
||||
|
||||
print("s = named.Slice()")
|
||||
s = named.Slice()
|
||||
|
@ -116,7 +120,7 @@ print("s = named.Slice(range(10))")
|
|||
s = named.Slice(range(10))
|
||||
print("s = %s" % (s,))
|
||||
|
||||
print("s = named.Slice(xrange(10))")
|
||||
s = named.Slice(xrange(10))
|
||||
print("s = %s" % (s,))
|
||||
|
||||
if _PY2:
|
||||
print("s = named.Slice(xrange(10))")
|
||||
s = named.Slice(xrange(10))
|
||||
print("s = %s" % (s,))
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright 2017 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 provides tools to generate bindings to use Go from Python.
|
||||
package bind
|
|
@ -16,6 +16,7 @@ const (
|
|||
// """)
|
||||
// discuss: https://github.com/go-python/gopy/pull/93#discussion_r119652220
|
||||
cffiPreamble = `"""%[1]s"""
|
||||
import collections
|
||||
import os
|
||||
import sys
|
||||
import cffi as _cffi_backend
|
||||
|
@ -56,6 +57,7 @@ extern void cgopy_incref(void* p0);
|
|||
extern void cgopy_decref(void* p0);
|
||||
|
||||
extern void cgo_pkg_%[2]s_init();
|
||||
|
||||
`
|
||||
cffiHelperPreamble = `""")
|
||||
|
||||
|
@ -230,6 +232,17 @@ func (g *cffiGen) genWrappedPy() {
|
|||
n := g.pkg.pkg.Name()
|
||||
g.wrapper.Printf(cffiHelperPreamble, n)
|
||||
g.wrapper.Indent()
|
||||
|
||||
// first, process slices, arrays
|
||||
names := g.pkg.syms.names()
|
||||
for _, n := range names {
|
||||
sym := g.pkg.syms.sym(n)
|
||||
if !sym.isType() {
|
||||
continue
|
||||
}
|
||||
g.genTypeConverter(sym)
|
||||
}
|
||||
|
||||
for _, s := range g.pkg.structs {
|
||||
g.genStructConversion(s)
|
||||
}
|
||||
|
@ -240,6 +253,14 @@ func (g *cffiGen) genWrappedPy() {
|
|||
g.wrapper.Printf("# make sure Cgo is loaded and initialized\n")
|
||||
g.wrapper.Printf("_cffi_helper.lib.cgo_pkg_%[1]s_init()\n", n)
|
||||
|
||||
for _, n := range names {
|
||||
sym := g.pkg.syms.sym(n)
|
||||
if !sym.isType() {
|
||||
continue
|
||||
}
|
||||
g.genType(sym)
|
||||
}
|
||||
|
||||
for _, s := range g.pkg.structs {
|
||||
g.genStruct(s)
|
||||
}
|
||||
|
|
|
@ -5,18 +5,22 @@
|
|||
package bind
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// genCdefStruct generates C definitions for a Go struct.
|
||||
func (g *cffiGen) genCdefStruct(s Struct) {
|
||||
g.wrapper.Printf("// A type definition of the %[1]s.%[2]s for wrapping.\n", s.Package().Name(), s.sym.cgoname)
|
||||
g.wrapper.Printf("typedef void* %s;\n", s.sym.cgoname)
|
||||
g.wrapper.Printf("extern void* cgo_func_%s_new();\n", s.sym.id)
|
||||
}
|
||||
|
||||
// genCdefType generates C definitions for a Go type.
|
||||
func (g *cffiGen) genCdefType(sym *symbol) {
|
||||
g.wrapper.Printf("// C definitions for Go type %[1]s.%[2]s.\n", g.pkg.pkg.Name(), sym.id)
|
||||
if !sym.isType() {
|
||||
return
|
||||
}
|
||||
|
@ -29,14 +33,64 @@ func (g *cffiGen) genCdefType(sym *symbol) {
|
|||
return
|
||||
}
|
||||
|
||||
g.genTypeCdefInit(sym)
|
||||
|
||||
if sym.isNamed() {
|
||||
typ := sym.GoType().(*types.Named)
|
||||
for imeth := 0; imeth < typ.NumMethods(); imeth++ {
|
||||
m := typ.Method(imeth)
|
||||
if !m.Exported() {
|
||||
continue
|
||||
}
|
||||
mname := types.ObjectString(m, nil)
|
||||
msym := g.pkg.syms.sym(mname)
|
||||
if msym == nil {
|
||||
panic(fmt.Errorf(
|
||||
"gopy: could not find symbol for [%[1]T] (%#[1]v) (%[2]s)",
|
||||
m.Type(),
|
||||
m.Name()+" || "+m.FullName(),
|
||||
))
|
||||
}
|
||||
g.genTypeCdefFunc(sym, msym)
|
||||
}
|
||||
}
|
||||
g.genCdefTypeTPStr(sym)
|
||||
g.wrapper.Printf("\n")
|
||||
}
|
||||
|
||||
// genTypeCdefInit generates cgo_func_XXXX_new() for a Go type.
|
||||
func (g *cffiGen) genTypeCdefInit(sym *symbol) {
|
||||
if sym.isBasic() {
|
||||
btyp := g.pkg.syms.symtype(sym.GoType().Underlying())
|
||||
g.wrapper.Printf("typedef %s %s;\n\n", btyp.cgoname, sym.cgoname)
|
||||
g.wrapper.Printf("typedef %[1]s %[2]s;\n", btyp.cgoname, sym.cgoname)
|
||||
g.wrapper.Printf("extern %[1]s cgo_func_%[2]s_new();\n", btyp.cgoname, sym.id)
|
||||
} else {
|
||||
g.wrapper.Printf("typedef void* %s;\n\n", sym.cgoname)
|
||||
g.wrapper.Printf("typedef void* %s;\n", sym.cgoname)
|
||||
g.wrapper.Printf("extern void* cgo_func_%s_new();\n", sym.id)
|
||||
}
|
||||
|
||||
switch {
|
||||
case sym.isBasic():
|
||||
case sym.isArray():
|
||||
typ := sym.GoType().Underlying().(*types.Array)
|
||||
elemType := g.pkg.syms.symtype(typ.Elem())
|
||||
g.wrapper.Printf("extern void cgo_func_%[1]s_ass_item(void* p0, GoInt p1, %[2]s p2);\n", sym.id, elemType.cgoname)
|
||||
case sym.isSlice():
|
||||
typ := sym.GoType().Underlying().(*types.Slice)
|
||||
elemType := g.pkg.syms.symtype(typ.Elem())
|
||||
g.wrapper.Printf("extern void cgo_func_%[1]s_append(void* p0, %[2]s p1);\n", sym.id, elemType.cgoname)
|
||||
case sym.isMap():
|
||||
case sym.isSignature():
|
||||
case sym.isInterface():
|
||||
default:
|
||||
panic(fmt.Errorf(
|
||||
"gopy: cdef for %s not handled",
|
||||
sym.gofmt(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// genCdefFunc generates a C definition for a Go function.
|
||||
func (g *cffiGen) genCdefFunc(f Func) {
|
||||
var params []string
|
||||
var retParams []string
|
||||
|
@ -68,6 +122,51 @@ func (g *cffiGen) genCdefFunc(f Func) {
|
|||
g.wrapper.Printf("extern %[1]s cgo_func_%[2]s(%[3]s);\n", cdef_ret, f.id, paramString)
|
||||
}
|
||||
|
||||
// genTypeCdefFunc generates a C definition for a Go type's method.
|
||||
func (g *cffiGen) genTypeCdefFunc(sym *symbol, fsym *symbol) {
|
||||
if !sym.isType() {
|
||||
return
|
||||
}
|
||||
|
||||
if sym.isStruct() {
|
||||
return
|
||||
}
|
||||
|
||||
if sym.isBasic() && !sym.isNamed() {
|
||||
return
|
||||
}
|
||||
isMethod := (sym != nil)
|
||||
sig := fsym.GoType().Underlying().(*types.Signature)
|
||||
args := sig.Params()
|
||||
res := sig.Results()
|
||||
var cdef_ret string
|
||||
var params []string
|
||||
switch res.Len() {
|
||||
case 0:
|
||||
cdef_ret = "void"
|
||||
case 1:
|
||||
ret := res.At(0)
|
||||
cdef_ret = g.pkg.syms.symtype(ret.Type()).cgoname
|
||||
}
|
||||
|
||||
if isMethod {
|
||||
params = append(params, sym.cgoname+" p0")
|
||||
}
|
||||
|
||||
for i := 0; i < args.Len(); i++ {
|
||||
arg := args.At(i)
|
||||
index := i
|
||||
if isMethod {
|
||||
index++
|
||||
}
|
||||
paramVar := g.pkg.syms.symtype(arg.Type()).cgoname + " " + "p" + strconv.Itoa(index)
|
||||
params = append(params, paramVar)
|
||||
}
|
||||
paramString := strings.Join(params, ", ")
|
||||
g.wrapper.Printf("extern %[1]s cgo_func_%[2]s(%[3]s);\n", cdef_ret, fsym.id, paramString)
|
||||
}
|
||||
|
||||
// genCdefMethod generates a C definition for a Go Struct's method.
|
||||
func (g *cffiGen) genCdefMethod(f Func) {
|
||||
var retParams []string
|
||||
var cdef_ret string
|
||||
|
@ -99,6 +198,7 @@ func (g *cffiGen) genCdefMethod(f Func) {
|
|||
g.wrapper.Printf("extern %[1]s cgo_func_%[2]s(%[3]s);\n", cdef_ret, f.id, paramString)
|
||||
}
|
||||
|
||||
// genCdefStructMemberGetter generates C definitions of Getter/Setter for a Go struct.
|
||||
func (g *cffiGen) genCdefStructMemberGetter(s Struct, i int, f types.Object) {
|
||||
pkg := s.Package()
|
||||
ft := f.Type()
|
||||
|
@ -116,6 +216,7 @@ func (g *cffiGen) genCdefStructMemberGetter(s Struct, i int, f types.Object) {
|
|||
}
|
||||
}
|
||||
|
||||
// genCdefStructMemberSetter generates C defintion of Setter for a Go struct.
|
||||
func (g *cffiGen) genCdefStructMemberSetter(s Struct, i int, f types.Object) {
|
||||
pkg := s.Package()
|
||||
ft := f.Type()
|
||||
|
@ -126,6 +227,12 @@ func (g *cffiGen) genCdefStructMemberSetter(s Struct, i int, f types.Object) {
|
|||
g.wrapper.Printf("extern void cgo_func_%[1]s_setter_%[2]d(void* p0, %[3]s p1);\n", s.sym.id, i+1, cdef_value)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package bind
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -21,7 +22,7 @@ func (g *cffiGen) genMethod(s Struct, m Func) {
|
|||
g.wrapper.Printf(`
|
||||
# pythonization of: %[1]s.%[2]s
|
||||
def %[2]s(%[3]s):
|
||||
"""%[4]s"""
|
||||
""%[4]q""
|
||||
`,
|
||||
g.pkg.pkg.Name(),
|
||||
m.GoName(),
|
||||
|
@ -117,7 +118,7 @@ func (g *cffiGen) genFunc(o Func) {
|
|||
g.wrapper.Printf(`
|
||||
# pythonization of: %[1]s.%[2]s
|
||||
def %[2]s(%[3]s):
|
||||
"""%[4]s"""
|
||||
""%[4]q""
|
||||
`,
|
||||
g.pkg.pkg.Name(),
|
||||
o.GoName(),
|
||||
|
@ -253,3 +254,76 @@ func (g *cffiGen) genFuncBody(f Func) {
|
|||
panic(fmt.Errorf("gopy: Not yet implemeted for multiple return."))
|
||||
}
|
||||
}
|
||||
|
||||
func (g *cffiGen) genTypeFunc(sym *symbol, fsym *symbol) {
|
||||
isMethod := (sym != nil)
|
||||
sig := fsym.GoType().Underlying().(*types.Signature)
|
||||
args := sig.Params()
|
||||
nargs := 0
|
||||
var funcArgs []string
|
||||
|
||||
if isMethod {
|
||||
funcArgs = append(funcArgs, "self")
|
||||
}
|
||||
|
||||
if args != nil {
|
||||
nargs = args.Len()
|
||||
for i := 0; i < nargs; i++ {
|
||||
arg := args.At(i)
|
||||
if args == nil {
|
||||
panic(fmt.Errorf(
|
||||
"gopy: could not find symbol for %q",
|
||||
arg.String(),
|
||||
))
|
||||
}
|
||||
funcArgs = append(funcArgs, arg.Name())
|
||||
}
|
||||
}
|
||||
|
||||
g.wrapper.Printf(
|
||||
`def %[1]s(%[2]s):
|
||||
""%[3]q""
|
||||
`,
|
||||
fsym.goname,
|
||||
strings.Join(funcArgs, ", "),
|
||||
fsym.doc,
|
||||
)
|
||||
g.wrapper.Indent()
|
||||
g.genTypeFuncBody(sym, fsym)
|
||||
g.wrapper.Outdent()
|
||||
}
|
||||
|
||||
func (g *cffiGen) genTypeFuncBody(sym *symbol, fsym *symbol) {
|
||||
isMethod := (sym != nil)
|
||||
sig := fsym.GoType().Underlying().(*types.Signature)
|
||||
args := sig.Params()
|
||||
res := sig.Results()
|
||||
nargs := 0
|
||||
nres := 0
|
||||
var funcArgs []string
|
||||
if isMethod {
|
||||
funcArgs = append(funcArgs, "self.cgopy")
|
||||
}
|
||||
|
||||
if args != nil {
|
||||
nargs = args.Len()
|
||||
for i := 0; i < nargs; i++ {
|
||||
arg := args.At(i)
|
||||
funcArgs = append(funcArgs, arg.Name())
|
||||
}
|
||||
}
|
||||
|
||||
if res != nil {
|
||||
nres = res.Len()
|
||||
}
|
||||
|
||||
if nres > 0 {
|
||||
g.wrapper.Printf("res = ")
|
||||
g.wrapper.Printf("_cffi_helper.lib.cgo_func_%[1]s(%[2]s)\n", fsym.id, strings.Join(funcArgs, ", "))
|
||||
ret := res.At(0)
|
||||
sret := g.pkg.syms.symtype(ret.Type())
|
||||
g.wrapper.Printf("return _cffi_helper.cffi_%[1]s(res)\n", sret.c2py)
|
||||
} else {
|
||||
g.wrapper.Printf("_cffi_helper.lib.cgo_func_%[1]s(%[2]s)\n", fsym.id, strings.Join(funcArgs, ", "))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ func (g *cffiGen) genStruct(s Struct) {
|
|||
g.wrapper.Printf(`
|
||||
# Python type for struct %[1]s.%[2]s
|
||||
class %[2]s(object):
|
||||
"""%[3]s"""
|
||||
""%[3]q""
|
||||
`,
|
||||
pkgname,
|
||||
s.GoName(),
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
// Copyright 2017 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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
// genType generates a Python class wrapping the given Go type.
|
||||
func (g *cffiGen) genType(sym *symbol) {
|
||||
if !sym.isType() {
|
||||
return
|
||||
}
|
||||
if sym.isStruct() {
|
||||
return
|
||||
}
|
||||
if sym.isBasic() && !sym.isNamed() {
|
||||
return
|
||||
}
|
||||
|
||||
pkgname := g.pkg.pkg.Name()
|
||||
g.wrapper.Printf(`
|
||||
# Python type for %[1]s.%[2]s
|
||||
class %[2]s(object):
|
||||
""%[3]q""
|
||||
`, pkgname,
|
||||
sym.goname,
|
||||
sym.doc,
|
||||
)
|
||||
g.wrapper.Indent()
|
||||
g.genTypeInit(sym)
|
||||
g.genTypeMethod(sym)
|
||||
g.genTypeTPStr(sym)
|
||||
if sym.isSlice() {
|
||||
g.genTypeIAdd(sym)
|
||||
}
|
||||
g.wrapper.Outdent()
|
||||
}
|
||||
|
||||
// genTypeIAdd generates Type __iadd__.
|
||||
func (g *cffiGen) genTypeIAdd(sym *symbol) {
|
||||
g.wrapper.Printf("def __iadd__(self, value):\n")
|
||||
g.wrapper.Indent()
|
||||
switch {
|
||||
case sym.isSlice():
|
||||
g.wrapper.Printf("if not isinstance(value, collections.Iterable):\n")
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("raise TypeError('%[1]s.__iadd__ takes a iterable type as argument')\n", sym.goname)
|
||||
g.wrapper.Outdent()
|
||||
typ := sym.GoType().Underlying().(*types.Slice)
|
||||
esym := g.pkg.syms.symtype(typ.Elem())
|
||||
g.wrapper.Printf("for elt in value:\n")
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("pyitem = _cffi_helper.cffi_%[1]s(elt)\n", esym.py2c)
|
||||
g.wrapper.Printf("_cffi_helper.lib.cgo_func_%[1]s_append(self.cgopy, pyitem)\n", sym.id)
|
||||
g.wrapper.Outdent()
|
||||
default:
|
||||
panic(fmt.Errorf(
|
||||
"gopy: __iadd__ for %s not handled",
|
||||
sym.gofmt(),
|
||||
))
|
||||
}
|
||||
g.wrapper.Printf("return self\n")
|
||||
g.wrapper.Outdent()
|
||||
g.wrapper.Printf("\n")
|
||||
}
|
||||
|
||||
// genTypeInit generates Type __init__.
|
||||
func (g *cffiGen) genTypeInit(sym *symbol) {
|
||||
nargs := 1
|
||||
g.wrapper.Printf("def __init__(self, *args, **kwargs):\n")
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("nkwds = len(kwargs)\n")
|
||||
g.wrapper.Printf("nargs = len(args)\n")
|
||||
g.wrapper.Printf("if nkwds + nargs > %[1]d:\n", nargs)
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("raise TypeError('%s.__init__ takes at most %d argument(s)')\n",
|
||||
sym.goname,
|
||||
nargs,
|
||||
)
|
||||
g.wrapper.Outdent()
|
||||
g.wrapper.Printf("self.cgopy = _cffi_helper.lib.cgo_func_%[1]s_new()\n", sym.id)
|
||||
switch {
|
||||
case sym.isBasic():
|
||||
bsym := g.pkg.syms.symtype(sym.GoType().Underlying())
|
||||
g.wrapper.Printf("if len(args) == 1:\n")
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("self.cgopy = _cffi_helper.cffi_%[1]s(args[0])\n",
|
||||
bsym.py2c,
|
||||
)
|
||||
g.wrapper.Outdent()
|
||||
case sym.isArray():
|
||||
g.wrapper.Printf("if args:\n")
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("if not isinstance(args[0], collections.Sequence):\n")
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("raise TypeError('%[1]s.__init__ takes a sequence as argument')\n", sym.goname)
|
||||
g.wrapper.Outdent()
|
||||
typ := sym.GoType().Underlying().(*types.Array)
|
||||
esym := g.pkg.syms.symtype(typ.Elem())
|
||||
g.wrapper.Printf("if len(args[0]) > %[1]d:\n", typ.Len())
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("raise ValueError('%[1]s.__init__ takes a sequence of size at most %[2]d')\n",
|
||||
sym.goname,
|
||||
typ.Len(),
|
||||
)
|
||||
g.wrapper.Outdent()
|
||||
g.wrapper.Printf("for idx, elt in enumerate(args[0]):\n")
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("pyitem = _cffi_helper.cffi_%[1]s(elt)\n", esym.py2c)
|
||||
g.wrapper.Printf("_cffi_helper.lib.cgo_func_%[1]s_ass_item(self.cgopy, idx, pyitem)\n", sym.id)
|
||||
g.wrapper.Outdent()
|
||||
g.wrapper.Outdent()
|
||||
case sym.isSlice():
|
||||
g.wrapper.Printf("if args:\n")
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("if not isinstance(args[0], collections.Iterable):\n")
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("raise TypeError('%[1]s.__init__ takes a sequence as argument')\n", sym.goname)
|
||||
g.wrapper.Outdent()
|
||||
typ := sym.GoType().Underlying().(*types.Slice)
|
||||
esym := g.pkg.syms.symtype(typ.Elem())
|
||||
g.wrapper.Printf("for elt in args[0]:\n")
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("pyitem = _cffi_helper.cffi_%[1]s(elt)\n", esym.py2c)
|
||||
g.wrapper.Printf("_cffi_helper.lib.cgo_func_%[1]s_append(self.cgopy, pyitem)\n", sym.id)
|
||||
g.wrapper.Outdent()
|
||||
g.wrapper.Outdent()
|
||||
case sym.isMap():
|
||||
case sym.isSignature():
|
||||
//TODO(corona10)
|
||||
case sym.isInterface():
|
||||
//TODO(corona10)
|
||||
default:
|
||||
panic(fmt.Errorf(
|
||||
"gopy: init for %s not handled",
|
||||
sym.gofmt(),
|
||||
))
|
||||
}
|
||||
g.wrapper.Outdent()
|
||||
g.wrapper.Printf("\n")
|
||||
}
|
||||
|
||||
// genTypeConverter generates a Type converter between C and Python.
|
||||
func (g *cffiGen) genTypeConverter(sym *symbol) {
|
||||
g.wrapper.Printf("# converters for %s - %s\n", sym.id, sym.goname)
|
||||
g.wrapper.Printf("@staticmethod\n")
|
||||
g.wrapper.Printf("def cffi_cgopy_cnv_py2c_%[1]s(o):\n", sym.id)
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("raise NotImplementedError\n")
|
||||
g.wrapper.Outdent()
|
||||
g.wrapper.Printf("\n")
|
||||
g.wrapper.Printf("@staticmethod\n")
|
||||
g.wrapper.Printf("def cffi_cgopy_cnv_c2py_%[1]s(c):\n", sym.id)
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("raise NotImplementedError\n")
|
||||
g.wrapper.Outdent()
|
||||
g.wrapper.Printf("\n")
|
||||
}
|
||||
|
||||
// genTypeMethod generates Type methods.
|
||||
func (g *cffiGen) genTypeMethod(sym *symbol) {
|
||||
g.wrapper.Printf("# methods for %s\n", sym.gofmt())
|
||||
if sym.isNamed() {
|
||||
typ := sym.GoType().(*types.Named)
|
||||
for imeth := 0; imeth < typ.NumMethods(); imeth++ {
|
||||
m := typ.Method(imeth)
|
||||
if !m.Exported() {
|
||||
continue
|
||||
}
|
||||
mname := types.ObjectString(m, nil)
|
||||
msym := g.pkg.syms.sym(mname)
|
||||
if msym == nil {
|
||||
panic(fmt.Errorf(
|
||||
"gopy: could not find symbol for [%[1]T] (%#[1]v) (%[2]s)",
|
||||
m.Type(),
|
||||
m.Name()+" || "+m.FullName(),
|
||||
))
|
||||
}
|
||||
g.genTypeFunc(sym, msym)
|
||||
}
|
||||
}
|
||||
g.wrapper.Printf("\n")
|
||||
}
|
||||
|
||||
// genTypeTPStr generates Type __str__ method.
|
||||
func (g *cffiGen) genTypeTPStr(sym *symbol) {
|
||||
g.wrapper.Printf("def __str__(self):\n")
|
||||
g.wrapper.Indent()
|
||||
g.wrapper.Printf("cret = _cffi_helper.lib.cgo_func_%[1]s_str(self.cgopy)\n", sym.id)
|
||||
g.wrapper.Printf("ret = _cffi_helper.cffi_cgopy_cnv_c2py_string(cret)\n")
|
||||
g.wrapper.Printf("return ret\n")
|
||||
g.wrapper.Outdent()
|
||||
g.wrapper.Printf("\n")
|
||||
}
|
88
main_test.go
88
main_test.go
|
@ -499,6 +499,72 @@ s = named.Slice(range(10))
|
|||
s = named.Slice{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
s = named.Slice(xrange(10))
|
||||
s = named.Slice{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
`),
|
||||
})
|
||||
|
||||
testPkgWithCFFI(t, pkg{
|
||||
path: "_examples/named",
|
||||
want: []byte(`doc(named): 'package named tests various aspects of named types.\n'
|
||||
doc(named.Float): ''
|
||||
doc(named.Float.Value): 'Value() float\n\nValue returns a float32 value\n'
|
||||
v = named.Float()
|
||||
v = 0
|
||||
v.Value() = 0.0
|
||||
x = named.X()
|
||||
x = 0
|
||||
x.Value() = 0.0
|
||||
x = named.XX()
|
||||
x = 0
|
||||
x.Value() = 0.0
|
||||
x = named.XXX()
|
||||
x = 0
|
||||
x.Value() = 0.0
|
||||
x = named.XXXX()
|
||||
x = 0
|
||||
x.Value() = 0.0
|
||||
v = named.Float(42)
|
||||
v = 42
|
||||
v.Value() = 42.0
|
||||
v = named.Float(42.0)
|
||||
v = 42
|
||||
v.Value() = 42.0
|
||||
x = named.X(42)
|
||||
x = 42
|
||||
x.Value() = 42.0
|
||||
x = named.XX(42)
|
||||
x = 42
|
||||
x.Value() = 42.0
|
||||
x = named.XXX(42)
|
||||
x = 42
|
||||
x.Value() = 42.0
|
||||
x = named.XXXX(42)
|
||||
x = 42
|
||||
x.Value() = 42.0
|
||||
x = named.XXXX(42.0)
|
||||
x = 42
|
||||
x.Value() = 42.0
|
||||
s = named.Str()
|
||||
s = ""
|
||||
s.Value() = ''
|
||||
s = named.Str('string')
|
||||
s = "string"
|
||||
s.Value() = 'string'
|
||||
arr = named.Array()
|
||||
arr = named.Array{0, 0}
|
||||
arr = named.Array([1,2])
|
||||
arr = named.Array{1, 2}
|
||||
arr = named.Array(range(10))
|
||||
caught: Array.__init__ takes a sequence of size at most 2
|
||||
arr = named.Array(xrange(2))
|
||||
arr = named.Array{0, 1}
|
||||
s = named.Slice()
|
||||
s = named.Slice(nil)
|
||||
s = named.Slice([1,2])
|
||||
s = named.Slice{1, 2}
|
||||
s = named.Slice(range(10))
|
||||
s = named.Slice{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
s = named.Slice(xrange(10))
|
||||
s = named.Slice{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
`),
|
||||
})
|
||||
}
|
||||
|
@ -663,6 +729,28 @@ s += [1,2]
|
|||
s = seqs.Slice{1, 2}
|
||||
s += [10,20]
|
||||
s = seqs.Slice{1, 2, 10, 20}
|
||||
`),
|
||||
})
|
||||
|
||||
testPkgWithCFFI(t, pkg{
|
||||
path: "_examples/seqs",
|
||||
want: []byte(`doc(seqs): 'package seqs tests various aspects of sequence types.\n'
|
||||
arr = seqs.Array(xrange(2))
|
||||
arr = seqs.Array{0, 1, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
s = seqs.Slice()
|
||||
s = seqs.Slice(nil)
|
||||
s = seqs.Slice([1,2])
|
||||
s = seqs.Slice{1, 2}
|
||||
s = seqs.Slice(range(10))
|
||||
s = seqs.Slice{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
s = seqs.Slice(xrange(10))
|
||||
s = seqs.Slice{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
s = seqs.Slice()
|
||||
s = seqs.Slice(nil)
|
||||
s += [1,2]
|
||||
s = seqs.Slice{1, 2}
|
||||
s += [10,20]
|
||||
s = seqs.Slice{1, 2, 10, 20}
|
||||
`),
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue