Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions _examples/hi/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,11 @@
arr[1] = 42
print "arr:",arr
print "len(arr):",len(arr)
print "mem(arr):",len(memoryview(arr))
try:
print "mem(arr):",len(memoryview(arr))
except Exception, err:
print "caught:",err
pass

print "--- testing slice..."
s = hi.GetIntSlice()
Expand All @@ -245,5 +249,7 @@
s[1] = 42
print "slice:",s
print "len(slice):",len(s)
print "mem(slice):",len(memoryview(s))

try:
print "mem(slice):",len(memoryview(s))
except Exception as err:
print "caught:",err
3 changes: 3 additions & 0 deletions bind/gencffi_cdef.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,13 @@ func (g *cffiGen) genTypeCdefInit(sym *symbol) {
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)
g.wrapper.Printf("extern %[1]s cgo_func_%[2]s_item(void* p0, %[1]s p1);\n", elemType.cgoname, sym.id)
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_ass_item(void* p0, GoInt p1, %[2]s p2);\n", sym.id, elemType.cgoname)
g.wrapper.Printf("extern void cgo_func_%[1]s_append(void* p0, %[2]s p1);\n", sym.id, elemType.cgoname)
g.wrapper.Printf("extern %[1]s cgo_func_%[2]s_item(void* p0, %[1]s p1);\n", elemType.cgoname, sym.id)
case sym.isMap():
case sym.isSignature():
case sym.isInterface():
Expand Down
16 changes: 16 additions & 0 deletions bind/gencffi_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class %[2]s(object):
g.genStructInit(s)
g.genStructMembers(s)
g.genStructMethods(s)
g.genStructTPRepr(s)
g.genStructTPStr(s)
g.wrapper.Outdent()
}
Expand Down Expand Up @@ -103,6 +104,10 @@ func (g *cffiGen) genStructInit(s Struct) {
g.wrapper.Outdent()
g.wrapper.Printf("if %[1]s != None:\n", kwd_name)
g.wrapper.Indent()
g.wrapper.Printf("if not isinstance(%[1]s, %[2]s):\n", kwd_name, ifield.sym.pysig)
g.wrapper.Indent()
g.wrapper.Printf("raise TypeError(\"invalid type for '%[1]s' attribute\")\n", field.Name())
g.wrapper.Outdent()
if ifield.sym.hasConverter() {
g.wrapper.Printf("c_kwd_%03[1]d = _cffi_helper.cffi_%[2]s(py_kwd_%03[1]d)\n", i+1, ifield.sym.py2c)
g.wrapper.Printf("%[1]s(self.cgopy, c_kwd_%03d)\n", cgo_fsetname, i+1)
Expand Down Expand Up @@ -184,11 +189,22 @@ func (g *cffiGen) genStructMethods(s Struct) {
}
}

func (g *cffiGen) genStructTPRepr(s Struct) {
g.wrapper.Printf("def __repr__(self):\n")
g.wrapper.Indent()
g.wrapper.Printf("cret = _cffi_helper.lib.cgo_func_%[1]s_str(self.cgopy)\n", s.sym.id)
g.wrapper.Printf("ret = _cffi_helper.cffi_cgopy_cnv_c2py_string(cret)\n")
g.wrapper.Printf("return ret\n")
g.wrapper.Printf("\n")
g.wrapper.Outdent()
}

func (g *cffiGen) genStructTPStr(s Struct) {
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", s.sym.id)
g.wrapper.Printf("ret = _cffi_helper.cffi_cgopy_cnv_c2py_string(cret)\n")
g.wrapper.Printf("return ret\n")
g.wrapper.Printf("\n")
g.wrapper.Outdent()
}
131 changes: 127 additions & 4 deletions bind/gencffi_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,39 @@ func (g *cffiGen) genType(sym *symbol) {
return
}

var typename string

if sym.isNamed() {
typename = sym.goname
} else {
typename = sym.cgoname
}

pkgname := g.pkg.pkg.Name()
g.wrapper.Printf(`
# Python type for %[1]s.%[2]s
class %[2]s(object):
""%[3]q""
`, pkgname,
sym.goname,
typename,
sym.doc,
)
g.wrapper.Indent()
g.genTypeInit(sym)
g.genTypeMethod(sym)
g.genTypeTPRepr(sym)
g.genTypeTPStr(sym)

if sym.isPySequence() {
g.genTypeLen(sym)
g.genTypeGetItem(sym)
g.genTypeSetItem(sym)
}

if sym.isSlice() {
g.genTypeIAdd(sym)
}

g.wrapper.Outdent()
}

Expand Down Expand Up @@ -68,7 +85,41 @@ func (g *cffiGen) genTypeIAdd(sym *symbol) {
g.wrapper.Printf("\n")
}

// genTypeInit generates Type __init__.
// genTypeGetItem generates __getitem__ of a type.
func (g *cffiGen) genTypeGetItem(sym *symbol) {
g.wrapper.Printf("def __getitem__(self, idx):\n")
g.wrapper.Indent()
switch {
case sym.isArray():
g.wrapper.Printf("if idx >= len(self):\n")
g.wrapper.Indent()
g.wrapper.Printf("raise IndexError('array index out of range')\n")
g.wrapper.Outdent()
typ := sym.GoType().Underlying().(*types.Array)
esym := g.pkg.syms.symtype(typ.Elem())
g.wrapper.Printf("item = _cffi_helper.lib.cgo_func_%[1]s_item(self.cgopy, idx)\n", sym.id)
g.wrapper.Printf("pyitem = _cffi_helper.cffi_%[1]s(item)\n", esym.c2py)
case sym.isSlice():
g.wrapper.Printf("if idx >= len(self):\n")
g.wrapper.Indent()
g.wrapper.Printf("raise IndexError('slice index out of range')\n")
g.wrapper.Outdent()
typ := sym.GoType().Underlying().(*types.Slice)
esym := g.pkg.syms.symtype(typ.Elem())
g.wrapper.Printf("item = _cffi_helper.lib.cgo_func_%[1]s_item(self.cgopy, idx)\n", sym.id)
g.wrapper.Printf("pyitem = _cffi_helper.cffi_%[1]s(item)\n", esym.c2py)
default:
panic(fmt.Errorf(
"gopy: __getitem__ for %s not handled",
sym.gofmt(),
))
}
g.wrapper.Printf("return pyitem\n")
g.wrapper.Outdent()
g.wrapper.Printf("\n")
}

// genTypeInit generates __init__ of a type.
func (g *cffiGen) genTypeInit(sym *symbol) {
nargs := 1
g.wrapper.Printf("def __init__(self, *args, **kwargs):\n")
Expand Down Expand Up @@ -145,18 +196,46 @@ func (g *cffiGen) genTypeInit(sym *symbol) {
}

// genTypeConverter generates a Type converter between C and Python.
func (g *cffiGen) genTypeLen(sym *symbol) {
g.wrapper.Printf("def __len__(self):\n")
g.wrapper.Indent()
switch {
case sym.isArray():
typ := sym.GoType().Underlying().(*types.Array)
g.wrapper.Printf("return %[1]d\n", typ.Len())
case sym.isSlice():
g.wrapper.Printf("return ffi.cast('GoSlice*', self.cgopy).len\n")
default:
panic(fmt.Errorf(
"gopy: len for %s not handled",
sym.gofmt(),
))
}
g.wrapper.Outdent()
g.wrapper.Printf("\n")
}

// genTypeConverter generates Type converter between C and Python.
func (g *cffiGen) genTypeConverter(sym *symbol) {
var typename string
if sym.isNamed() {
typename = sym.goname
} else {
typename = sym.cgoname
}
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.Printf("return o.cgopy\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.Printf("o = %[1]s()\n", typename)
g.wrapper.Printf("o.cgopy = c\n")
g.wrapper.Printf("return o\n")
g.wrapper.Outdent()
g.wrapper.Printf("\n")
}
Expand Down Expand Up @@ -187,6 +266,17 @@ func (g *cffiGen) genTypeMethod(sym *symbol) {
}

// genTypeTPStr generates Type __str__ method.
func (g *cffiGen) genTypeTPRepr(sym *symbol) {
g.wrapper.Printf("def __repr__(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")
}

// genTypeTPStr generates __str__ method of a type.
func (g *cffiGen) genTypeTPStr(sym *symbol) {
g.wrapper.Printf("def __str__(self):\n")
g.wrapper.Indent()
Expand All @@ -196,3 +286,36 @@ func (g *cffiGen) genTypeTPStr(sym *symbol) {
g.wrapper.Outdent()
g.wrapper.Printf("\n")
}

// genTypeSetItem generates __setitem__ of a type.
func (g *cffiGen) genTypeSetItem(sym *symbol) {
g.wrapper.Printf("def __setitem__(self, idx, item):\n")
g.wrapper.Indent()
switch {
case sym.isArray():
g.wrapper.Printf("if idx >= len(self):\n")
g.wrapper.Indent()
g.wrapper.Printf("raise IndexError('array index out of range')\n")
g.wrapper.Outdent()
typ := sym.GoType().Underlying().(*types.Array)
esym := g.pkg.syms.symtype(typ.Elem())
g.wrapper.Printf("pyitem = _cffi_helper.cffi_%[1]s(item)\n", esym.py2c)
g.wrapper.Printf("_cffi_helper.lib.cgo_func_%[1]s_ass_item(self.cgopy, idx, pyitem)\n", sym.id)
case sym.isSlice():
g.wrapper.Printf("if idx >= len(self):\n")
g.wrapper.Indent()
g.wrapper.Printf("raise IndexError('slice index out of range')\n")
g.wrapper.Outdent()
typ := sym.GoType().Underlying().(*types.Slice)
esym := g.pkg.syms.symtype(typ.Elem())
g.wrapper.Printf("pyitem = _cffi_helper.cffi_%[1]s(item)\n", esym.py2c)
g.wrapper.Printf("_cffi_helper.lib.cgo_func_%[1]s_ass_item(self.cgopy, idx, pyitem)\n", sym.id)
default:
panic(fmt.Errorf(
"gopy: __setitem__ for %s not handled",
sym.gofmt(),
))
}
g.wrapper.Outdent()
g.wrapper.Printf("\n")
}
4 changes: 4 additions & 0 deletions bind/symtab.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ func (s symbol) isMap() bool {
return (s.kind & skMap) != 0
}

func (s symbol) isPySequence() bool {
return s.isArray() || s.isSlice()
}

func (s symbol) isSlice() bool {
return (s.kind & skSlice) != 0
}
Expand Down
Loading