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
22 changes: 13 additions & 9 deletions _examples/named/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__,))
Expand Down Expand Up @@ -96,13 +99,14 @@
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()
Expand All @@ -116,7 +120,7 @@
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,))
6 changes: 6 additions & 0 deletions bind/doc.go
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions bind/gencffi.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -56,6 +57,7 @@ extern void cgopy_incref(void* p0);
extern void cgopy_decref(void* p0);

extern void cgo_pkg_%[2]s_init();

`
cffiHelperPreamble = `""")

Expand Down Expand Up @@ -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)
}
Expand All @@ -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)
}
Expand Down
111 changes: 109 additions & 2 deletions bind/gencffi_cdef.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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()
Expand All @@ -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)
}
78 changes: 76 additions & 2 deletions bind/gencffi_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package bind

import (
"fmt"
"go/types"
"strings"
)

Expand All @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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, ", "))
}
}
2 changes: 1 addition & 1 deletion bind/gencffi_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Loading