cffi: Implement wrapping of functions with slices/arrays of builtin arguments

This commit is contained in:
Dong-hee Na 2017-08-05 09:49:02 +00:00 committed by Sebastien Binet
parent 61290c18b0
commit 31d6377e11
6 changed files with 126 additions and 0 deletions

View File

@ -0,0 +1,17 @@
// 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 arrays
func IntSum(a [4]int) int {
sum := 0
for i := 0; i < len(a); i++ {
sum += a[i]
}
return sum
}
func CreateArray() [4]int {
return [4]int{1, 2, 3, 4}
}

13
_examples/arrays/test.py Normal file
View File

@ -0,0 +1,13 @@
# 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.
from __future__ import print_function
import arrays
a = [1,2,3,4]
b = arrays.CreateArray()
print ("Python list:", a)
print ("Go array: ", b)
print ("arrays.IntSum from Python list:", arrays.IntSum(a))
print ("arrays.IntSum from Go array:", arrays.IntSum(b))

View File

@ -0,0 +1,17 @@
// 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 slices
func IntSum(s []int) int {
sum := 0
for _, value := range s {
sum += value
}
return sum
}
func CreateSlice() []int {
return []int{1, 2, 3, 4}
}

13
_examples/slices/test.py Normal file
View File

@ -0,0 +1,13 @@
# 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.
from __future__ import print_function
import slices
a = [1,2,3,4]
b = slices.CreateSlice()
print ("Python list:", a)
print ("Go slice: ", b)
print ("slices.IntSum from Python list:", slices.IntSum(a))
print ("slices.IntSum from Go slice:", slices.IntSum(b))

View File

@ -227,8 +227,50 @@ func (g *cffiGen) genTypeConverter(sym *symbol) {
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("if type(o) is %[1]s:\n", typename)
g.wrapper.Indent()
g.wrapper.Printf("return o.cgopy\n")
g.wrapper.Outdent()
switch {
case sym.isBasic():
g.wrapper.Printf("return _cffi_helper.cffi_cgopy_cnv_py2c_%[1]s(o)\n", sym.goname)
case sym.isArray():
g.wrapper.Printf("if not isinstance(o, 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.Array)
esym := g.pkg.syms.symtype(typ.Elem())
g.wrapper.Printf("if len(o) > %[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("c = _cffi_helper.lib.cgo_func_%[1]s_new()\n", sym.id)
g.wrapper.Printf("for idx, elt in enumerate(o):\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(c, idx, pyitem)\n", sym.id)
g.wrapper.Outdent()
g.wrapper.Printf("return c\n")
case sym.isSlice():
g.wrapper.Printf("if not isinstance(o, 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("c = _cffi_helper.lib.cgo_func_%[1]s_new()\n", sym.id)
g.wrapper.Printf("for elt in o:\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(c, pyitem)\n", sym.id)
g.wrapper.Outdent()
g.wrapper.Printf("return c\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)

View File

@ -932,3 +932,27 @@ pyerrors.Div(5, 2) = 2
`),
})
}
func TestBuiltinArrays(t *testing.T) {
t.Parallel()
testPkgWithCFFI(t, pkg{
path: "_examples/arrays",
want: []byte(`Python list: [1, 2, 3, 4]
Go array: [4]int{1, 2, 3, 4}
arrays.IntSum from Python list: 10
arrays.IntSum from Go array: 10
`),
})
}
func TestBuiltinSlices(t *testing.T) {
t.Parallel()
testPkgWithCFFI(t, pkg{
path: "_examples/slices",
want: []byte(`Python list: [1, 2, 3, 4]
Go slice: []int{1, 2, 3, 4}
slices.IntSum from Python list: 10
slices.IntSum from Go slice: 10
`),
})
}