bind: add __len__+__getitem__ support

Updates #9

Change-Id: Ifa4fc8b17c0ac2b4db0ded48ab33b2c6df9c1b3b
This commit is contained in:
Sebastien Binet 2015-08-05 17:44:26 +02:00
parent f06dcce095
commit 1fd60af396
2 changed files with 146 additions and 1 deletions

View File

@ -45,8 +45,10 @@ func (g *cpyGen) genType(sym *symbol) {
g.genTypeProtocols(sym)
asBuffer := "0"
asSequence := "0"
if sym.isArray() || sym.isSlice() {
asBuffer = fmt.Sprintf("&%[1]s_tp_as_buffer", sym.cpyname)
asSequence = fmt.Sprintf("&%[1]s_tp_as_sequence", sym.cpyname)
}
g.impl.Printf("static PyTypeObject %sType = {\n", sym.cpyname)
@ -63,7 +65,7 @@ func (g *cpyGen) genType(sym *symbol) {
g.impl.Printf("0,\t/*tp_compare*/\n")
g.impl.Printf("0,\t/*tp_repr*/\n")
g.impl.Printf("0,\t/*tp_as_number*/\n")
g.impl.Printf("0,\t/*tp_as_sequence*/\n")
g.impl.Printf("%s,\t/*tp_as_sequence*/\n", asSequence)
g.impl.Printf("0,\t/*tp_as_mapping*/\n")
g.impl.Printf("0,\t/*tp_hash */\n")
g.impl.Printf("0,\t/*tp_call*/\n")
@ -185,6 +187,7 @@ func (g *cpyGen) genTypeMethods(sym *symbol) {
func (g *cpyGen) genTypeProtocols(sym *symbol) {
g.genTypeTPStr(sym)
if sym.isSlice() || sym.isArray() {
g.genTypeTPAsSequence(sym)
g.genTypeTPAsBuffer(sym)
}
}
@ -217,6 +220,114 @@ func (g *cpyGen) genTypeTPStr(sym *symbol) {
g.impl.Printf("}\n\n")
}
func (g *cpyGen) genTypeTPAsSequence(sym *symbol) {
pkgname := g.pkg.pkg.Name()
g.decl.Printf("\n/* sequence support for %[1]s.%[2]s */\n",
pkgname, sym.goname,
)
var etyp types.Type
switch typ := sym.goobj.Type().(type) {
case *types.Array:
etyp = typ.Elem()
case *types.Slice:
etyp = typ.Elem()
}
esym := g.pkg.syms.symtype(etyp)
if esym == nil {
panic(fmt.Errorf("gopy: could not retrieve element type of %#v",
sym,
))
}
switch g.lang {
case 2:
g.decl.Printf("\n/* len */\n")
g.decl.Printf("static Py_ssize_t\ncpy_func_%[1]s_len(%[2]s *self);\n",
sym.id,
sym.cpyname,
)
g.impl.Printf("\n/* len */\n")
g.impl.Printf("static Py_ssize_t\ncpy_func_%[1]s_len(%[2]s *self) {\n",
sym.id,
sym.cpyname,
)
g.impl.Indent()
g.impl.Printf("GoSlice *slice = (GoSlice*)(self->cgopy);\n")
g.impl.Printf("return slice->len;\n")
g.impl.Outdent()
g.impl.Printf("}\n\n")
g.decl.Printf("\n/* item */\n")
g.decl.Printf("static PyObject*\n")
g.decl.Printf("cpy_func_%[1]s_item(%[2]s *self, Py_ssize_t i);\n",
sym.id,
sym.cpyname,
)
g.impl.Printf("\n/* item */\n")
g.impl.Printf("static PyObject*\n")
g.impl.Printf("cpy_func_%[1]s_item(%[2]s *self, Py_ssize_t i) {\n",
sym.id,
sym.cpyname,
)
g.impl.Indent()
g.impl.Printf("PyObject *pyitem = NULL;\n")
g.impl.Printf("GoSlice *slice = (GoSlice*)(self->cgopy);\n")
g.impl.Printf("if (i < 0 || i >= slice->len) {\n")
g.impl.Indent()
g.impl.Printf("PyErr_SetString(PyExc_IndexError, ")
g.impl.Printf("\"array index out of range\");\n")
g.impl.Printf("return NULL;\n")
g.impl.Outdent()
g.impl.Printf("}\n\n")
g.impl.Printf("%[1]s item = cgo_func_%[2]s_item(self->cgopy, i);\n",
esym.cgoname,
sym.id,
)
g.impl.Printf("pyitem = %[1]s(item);\n", esym.c2py)
g.impl.Printf("return pyitem;\n")
g.impl.Outdent()
g.impl.Printf("}\n\n")
g.impl.Printf("\n/* tp_as_sequence */\n")
g.impl.Printf("static PySequenceMethods %[1]s_tp_as_sequence = {\n", sym.cpyname)
g.impl.Indent()
g.impl.Printf("(lenfunc)cpy_func_%[1]s_len,\n", sym.id)
g.impl.Printf("(binaryfunc)0,\n") // array_concat, sq_concat
g.impl.Printf("(ssizeargfunc)0,\n") //array_repeat, /*sq_repeat
g.impl.Printf("(ssizeargfunc)cpy_func_%[1]s_item,\n", sym.id)
g.impl.Printf("(ssizessizeargfunc)0,\n") // array_slice, /*sq_slice
g.impl.Printf("(ssizeobjargproc)0,\n") //array_ass_item, /*sq_ass_item
g.impl.Printf("(ssizessizeobjargproc)0,\n") //array_ass_slice, /*sq_ass_slice
g.impl.Printf("(objobjproc)0,\n") //array_contains, /*sq_contains
g.impl.Printf("(binaryfunc)0,\n") //array_inplace_concat, /*sq_inplace_concat
g.impl.Printf("(ssizeargfunc)0\n") //array_inplace_repeat /*sq_inplace_repeat
g.impl.Outdent()
g.impl.Printf("};\n\n")
case 3:
}
/*
static PySequenceMethods array_as_sequence = {
(lenfunc)array_length, /*sq_length
(binaryfunc)array_concat, /*sq_concat
(ssizeargfunc)array_repeat, /*sq_repeat
(ssizeargfunc)array_item, /*sq_item
(ssizessizeargfunc)array_slice, /*sq_slice
(ssizeobjargproc)array_ass_item, /*sq_ass_item
(ssizessizeobjargproc)array_ass_slice, /*sq_ass_slice
(objobjproc)array_contains, /*sq_contains
(binaryfunc)array_inplace_concat, /*sq_inplace_concat
(ssizeargfunc)array_inplace_repeat /*sq_inplace_repeat
};
*/
}
func (g *cpyGen) genTypeTPAsBuffer(sym *symbol) {
pkgname := g.pkg.pkg.Name()
g.decl.Printf("\n/* buffer support for %[1]s.%[2]s */\n",

View File

@ -515,6 +515,20 @@ func (g *goGen) genType(sym *symbol) {
pkgname := sym.goobj.Pkg().Name()
var etyp types.Type
switch typ := sym.goobj.Type().(type) {
case *types.Array:
etyp = typ.Elem()
case *types.Slice:
etyp = typ.Elem()
}
esym := g.pkg.syms.symtype(etyp)
if esym == nil {
panic(fmt.Errorf("gopy: could not retrieve element type of %#v",
sym,
))
}
g.Printf("\n// --- wrapping %s.%s ---\n\n", pkgname, sym.goname)
g.Printf("//export %[1]s\n", sym.cgoname)
g.Printf("// %[1]s wraps %[2]s.%[3]s\n", sym.cgoname, pkgname, sym.goname)
@ -541,6 +555,26 @@ func (g *goGen) genType(sym *symbol) {
g.Printf("*(*%[1]s)(unsafe.Pointer(self)))\n", sym.goname)
g.Outdent()
g.Printf("}\n\n")
// support for __getitem__
g.Printf("//export cgo_func_%[1]s_item\n", sym.id)
g.Printf(
"func cgo_func_%[1]s_item(self %[2]s, i int) %[3]s {\n",
sym.id,
sym.cgoname,
esym.cgotypename(),
)
g.Indent()
g.Printf("arr := (*%[1]s)(unsafe.Pointer(self))\n", sym.goname)
g.Printf("elt := (*arr)[i]\n")
if needWrapType(etyp) {
g.Printf("cgopy_incref(unsafe.Pointer(&elt))\n")
g.Printf("return (%[1]s)(unsafe.Pointer(&elt))\n", esym.cgotypename())
} else {
g.Printf("return elt\n")
}
g.Outdent()
g.Printf("}\n\n")
}
func (g *goGen) genPreamble() {