2015-07-24 14:16:31 +00:00
|
|
|
// Copyright 2015 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 (
|
|
|
|
"go/token"
|
|
|
|
"path/filepath"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
cPreamble = `/*
|
|
|
|
C stubs for package %[1]s.
|
|
|
|
gopy gen -lang=python %[1]s
|
|
|
|
|
|
|
|
File is generated by gopy gen. Do not edit.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef _POSIX_C_SOURCE
|
|
|
|
#undef _POSIX_C_SOURCE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "Python.h"
|
|
|
|
#include "structmember.h"
|
2015-08-05 13:32:41 +00:00
|
|
|
#include "memoryobject.h"
|
|
|
|
#include "bufferobject.h"
|
2015-07-24 14:16:31 +00:00
|
|
|
|
|
|
|
// header exported from 'go tool cgo'
|
|
|
|
#include "%[3]s.h"
|
|
|
|
|
2015-07-31 14:51:30 +00:00
|
|
|
// helpers for cgopy
|
|
|
|
|
2015-08-05 16:55:55 +00:00
|
|
|
#define def_cnv(name, c2py, py2c, gotype) \
|
|
|
|
static int \
|
|
|
|
cgopy_cnv_py2c_ ## name(PyObject *o, gotype *addr) { \
|
|
|
|
*addr = py2c(o); \
|
|
|
|
return 1; \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
static PyObject* \
|
|
|
|
cgopy_cnv_c2py_ ## name(gotype *addr) { \
|
|
|
|
return c2py(*addr); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __X86_64__
|
|
|
|
def_cnv( int, PyLong_FromLong, PyLong_AsLong, GoInt)
|
|
|
|
def_cnv(uint, PyLong_FromUnsignedLong, PyLong_AsUnsignedLong, GoUint)
|
|
|
|
#else
|
|
|
|
def_cnv( int, PyInt_FromLong, PyInt_AsLong, GoInt)
|
|
|
|
def_cnv(uint, PyInt_FromLong, PyInt_AsLong, GoUint)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
def_cnv( int8, PyInt_FromLong, PyInt_AsLong, GoInt8)
|
|
|
|
def_cnv( int16, PyInt_FromLong, PyInt_AsLong, GoInt16)
|
|
|
|
def_cnv( int32, PyInt_FromLong, PyInt_AsLong, GoInt32)
|
|
|
|
def_cnv( int64, PyLong_FromLong, PyLong_AsLong, GoInt64)
|
|
|
|
def_cnv(uint8, PyInt_FromLong, PyInt_AsLong, GoUint8)
|
|
|
|
def_cnv(uint16, PyInt_FromLong, PyInt_AsLong, GoUint16)
|
|
|
|
def_cnv(uint32, PyInt_FromLong, PyInt_AsLong, GoUint32)
|
|
|
|
def_cnv(uint64, PyLong_FromUnsignedLong, PyLong_AsUnsignedLong, GoUint64)
|
|
|
|
|
|
|
|
def_cnv(float64, PyFloat_FromDouble, PyFloat_AsDouble, GoFloat64)
|
|
|
|
|
|
|
|
#undef def_cnv
|
|
|
|
|
2015-07-31 14:51:30 +00:00
|
|
|
static int
|
2015-08-04 13:51:41 +00:00
|
|
|
cgopy_cnv_py2c_bool(PyObject *o, GoUint8 *addr) {
|
2015-07-31 14:51:30 +00:00
|
|
|
*addr = (o == Py_True) ? 1 : 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject*
|
2015-08-04 13:51:41 +00:00
|
|
|
cgopy_cnv_c2py_bool(GoUint8 *addr) {
|
2015-07-31 14:51:30 +00:00
|
|
|
long v = *addr;
|
|
|
|
return PyBool_FromLong(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2015-08-04 13:51:41 +00:00
|
|
|
cgopy_cnv_py2c_string(PyObject *o, GoString *addr) {
|
2015-07-31 14:51:30 +00:00
|
|
|
const char *str = PyString_AsString(o);
|
|
|
|
if (str == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
2015-08-04 13:51:41 +00:00
|
|
|
*addr = _cgopy_GoString((char*)str);
|
2015-07-31 14:51:30 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject*
|
2015-08-04 13:51:41 +00:00
|
|
|
cgopy_cnv_c2py_string(GoString *addr) {
|
|
|
|
const char *str = _cgopy_CString(*addr);
|
2015-07-31 14:51:30 +00:00
|
|
|
PyObject *pystr = PyString_FromString(str);
|
|
|
|
free((void*)str);
|
|
|
|
return pystr;
|
|
|
|
}
|
2015-08-05 15:40:41 +00:00
|
|
|
|
|
|
|
static int
|
2015-08-05 16:55:55 +00:00
|
|
|
cgopy_cnv_py2c_float32(PyObject *o, GoFloat32 *addr) {
|
2015-08-05 15:40:41 +00:00
|
|
|
GoFloat32 v = PyFloat_AsDouble(o);
|
|
|
|
*addr = v;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject*
|
2015-08-05 16:55:55 +00:00
|
|
|
cgopy_cnv_c2py_float32(GoFloat32 *addr) {
|
2015-08-05 15:40:41 +00:00
|
|
|
GoFloat64 v = *addr;
|
|
|
|
return PyFloat_FromDouble(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cgopy_cnv_py2c_complex64(PyObject *o, GoComplex64 *addr) {
|
|
|
|
Py_complex v = PyComplex_AsCComplex(o);
|
|
|
|
*addr = v.real + v.imag * _Complex_I;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject*
|
|
|
|
cgopy_cnv_c2py_complex64(GoComplex64 *addr) {
|
|
|
|
return PyComplex_FromDoubles(creal(*addr), cimag(*addr));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cgopy_cnv_py2c_complex128(PyObject *o, GoComplex128 *addr) {
|
|
|
|
Py_complex v = PyComplex_AsCComplex(o);
|
|
|
|
*addr = v.real + v.imag * _Complex_I;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject*
|
|
|
|
cgopy_cnv_c2py_complex128(GoComplex128 *addr) {
|
|
|
|
return PyComplex_FromDoubles(creal(*addr), cimag(*addr));
|
|
|
|
}
|
2015-07-24 14:16:31 +00:00
|
|
|
`
|
|
|
|
)
|
|
|
|
|
|
|
|
type cpyGen struct {
|
|
|
|
decl *printer
|
|
|
|
impl *printer
|
|
|
|
|
|
|
|
fset *token.FileSet
|
|
|
|
pkg *Package
|
|
|
|
err ErrorList
|
2015-08-05 12:13:37 +00:00
|
|
|
|
|
|
|
lang int // c-python api version (2,3)
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (g *cpyGen) gen() error {
|
|
|
|
|
|
|
|
g.genPreamble()
|
|
|
|
|
2015-08-04 13:51:41 +00:00
|
|
|
// first, process slices, arrays
|
|
|
|
{
|
|
|
|
names := g.pkg.syms.names()
|
|
|
|
for _, n := range names {
|
|
|
|
sym := g.pkg.syms.sym(n)
|
|
|
|
if !sym.isType() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
g.genType(sym)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// then, process structs
|
2015-07-27 16:47:18 +00:00
|
|
|
for _, s := range g.pkg.structs {
|
2015-07-24 14:16:31 +00:00
|
|
|
g.genStruct(s)
|
|
|
|
}
|
|
|
|
|
2015-07-29 14:54:26 +00:00
|
|
|
// expose ctors at module level
|
|
|
|
// FIXME(sbinet): attach them to structs?
|
|
|
|
// -> problem is if one has 2 or more ctors with exactly the same signature.
|
|
|
|
for _, s := range g.pkg.structs {
|
|
|
|
for _, ctor := range s.ctors {
|
|
|
|
g.genFunc(ctor)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-27 16:47:18 +00:00
|
|
|
for _, f := range g.pkg.funcs {
|
|
|
|
g.genFunc(f)
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
2015-07-31 08:13:25 +00:00
|
|
|
for _, c := range g.pkg.consts {
|
|
|
|
g.genConst(c)
|
|
|
|
}
|
|
|
|
|
2015-07-31 14:52:12 +00:00
|
|
|
for _, v := range g.pkg.vars {
|
|
|
|
g.genVar(v)
|
|
|
|
}
|
|
|
|
|
2015-08-05 08:31:57 +00:00
|
|
|
g.impl.Printf("\n/* functions for package %s */\n", g.pkg.pkg.Name())
|
2015-07-27 16:47:18 +00:00
|
|
|
g.impl.Printf("static PyMethodDef cpy_%s_methods[] = {\n", g.pkg.pkg.Name())
|
2015-07-24 14:16:31 +00:00
|
|
|
g.impl.Indent()
|
2015-07-27 16:47:18 +00:00
|
|
|
for _, f := range g.pkg.funcs {
|
2015-07-28 10:27:15 +00:00
|
|
|
name := f.GoName()
|
2015-07-24 14:16:31 +00:00
|
|
|
//obj := scope.Lookup(name)
|
|
|
|
g.impl.Printf("{%[1]q, %[2]s, METH_VARARGS, %[3]q},\n",
|
2015-08-04 13:51:41 +00:00
|
|
|
name, "cpy_func_"+f.ID(), f.Doc(),
|
2015-07-24 14:16:31 +00:00
|
|
|
)
|
|
|
|
}
|
2015-07-29 14:54:26 +00:00
|
|
|
// expose ctors at module level
|
|
|
|
// FIXME(sbinet): attach them to structs?
|
|
|
|
// -> problem is if one has 2 or more ctors with exactly the same signature.
|
|
|
|
for _, s := range g.pkg.structs {
|
|
|
|
for _, f := range s.ctors {
|
|
|
|
name := f.GoName()
|
|
|
|
//obj := scope.Lookup(name)
|
|
|
|
g.impl.Printf("{%[1]q, %[2]s, METH_VARARGS, %[3]q},\n",
|
2015-08-04 13:51:41 +00:00
|
|
|
name, "cpy_func_"+f.ID(), f.Doc(),
|
2015-07-29 14:54:26 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-31 08:13:25 +00:00
|
|
|
for _, c := range g.pkg.consts {
|
|
|
|
name := c.GoName()
|
|
|
|
g.impl.Printf("{%[1]q, %[2]s, METH_VARARGS, %[3]q},\n",
|
2015-08-04 14:45:40 +00:00
|
|
|
"Get"+name, "cpy_func_"+c.id+"_get", c.Doc(),
|
2015-07-31 08:13:25 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2015-07-31 14:52:12 +00:00
|
|
|
for _, v := range g.pkg.vars {
|
|
|
|
name := v.Name()
|
|
|
|
g.impl.Printf("{%[1]q, %[2]s, METH_VARARGS, %[3]q},\n",
|
2015-08-04 14:45:40 +00:00
|
|
|
"Get"+name, "cpy_func_"+v.id+"_get", v.doc,
|
2015-07-31 14:52:12 +00:00
|
|
|
)
|
|
|
|
g.impl.Printf("{%[1]q, %[2]s, METH_VARARGS, %[3]q},\n",
|
2015-08-04 14:45:40 +00:00
|
|
|
"Set"+name, "cpy_func_"+v.id+"_set", v.doc,
|
2015-07-31 14:52:12 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2015-07-24 14:16:31 +00:00
|
|
|
g.impl.Printf("{NULL, NULL, 0, NULL} /* Sentinel */\n")
|
|
|
|
g.impl.Outdent()
|
|
|
|
g.impl.Printf("};\n\n")
|
|
|
|
|
|
|
|
g.impl.Printf("PyMODINIT_FUNC\ninit%[1]s(void)\n{\n", g.pkg.pkg.Name())
|
|
|
|
g.impl.Indent()
|
|
|
|
g.impl.Printf("PyObject *module = NULL;\n\n")
|
|
|
|
|
2015-08-05 08:32:38 +00:00
|
|
|
for _, n := range g.pkg.syms.names() {
|
|
|
|
sym := g.pkg.syms.sym(n)
|
|
|
|
if !sym.isType() {
|
|
|
|
continue
|
|
|
|
}
|
2015-07-28 09:47:55 +00:00
|
|
|
g.impl.Printf(
|
2015-08-04 13:51:41 +00:00
|
|
|
"if (PyType_Ready(&%sType) < 0) { return; }\n",
|
2015-08-05 08:32:38 +00:00
|
|
|
sym.cpyname,
|
2015-07-28 09:47:55 +00:00
|
|
|
)
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
2015-07-27 16:47:18 +00:00
|
|
|
g.impl.Printf("module = Py_InitModule3(%[1]q, cpy_%[1]s_methods, %[2]q);\n\n",
|
2015-07-24 14:16:31 +00:00
|
|
|
g.pkg.pkg.Name(),
|
|
|
|
g.pkg.doc.Doc,
|
|
|
|
)
|
|
|
|
|
2015-08-05 08:32:38 +00:00
|
|
|
for _, n := range g.pkg.syms.names() {
|
|
|
|
sym := g.pkg.syms.sym(n)
|
|
|
|
if !sym.isType() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
g.impl.Printf("Py_INCREF(&%sType);\n", sym.cpyname)
|
2015-08-04 13:51:41 +00:00
|
|
|
g.impl.Printf("PyModule_AddObject(module, %q, (PyObject*)&%sType);\n\n",
|
2015-08-05 08:32:38 +00:00
|
|
|
sym.goname,
|
|
|
|
sym.cpyname,
|
2015-07-24 14:16:31 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
g.impl.Outdent()
|
|
|
|
g.impl.Printf("}\n\n")
|
|
|
|
|
|
|
|
if len(g.err) > 0 {
|
|
|
|
return g.err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-07-31 08:13:25 +00:00
|
|
|
func (g *cpyGen) genConst(o Const) {
|
|
|
|
g.genFunc(o.f)
|
|
|
|
}
|
|
|
|
|
2015-07-31 14:52:12 +00:00
|
|
|
func (g *cpyGen) genVar(v Var) {
|
2015-07-31 16:01:49 +00:00
|
|
|
|
2015-07-31 14:52:12 +00:00
|
|
|
id := g.pkg.Name() + "_" + v.Name()
|
|
|
|
doc := v.doc
|
|
|
|
{
|
|
|
|
res := []*Var{newVar(g.pkg, v.GoType(), "ret", v.Name(), doc)}
|
|
|
|
sig := newSignature(g.pkg, nil, nil, res)
|
|
|
|
fget := Func{
|
|
|
|
pkg: g.pkg,
|
|
|
|
sig: sig,
|
|
|
|
typ: nil,
|
|
|
|
name: v.Name(),
|
2015-08-04 13:51:41 +00:00
|
|
|
id: id + "_get",
|
2015-07-31 14:52:12 +00:00
|
|
|
doc: "returns " + g.pkg.Name() + "." + v.Name(),
|
|
|
|
ret: v.GoType(),
|
|
|
|
err: false,
|
|
|
|
}
|
|
|
|
g.genFunc(fget)
|
|
|
|
}
|
|
|
|
{
|
|
|
|
params := []*Var{newVar(g.pkg, v.GoType(), "arg", v.Name(), doc)}
|
|
|
|
sig := newSignature(g.pkg, nil, params, nil)
|
|
|
|
fset := Func{
|
|
|
|
pkg: g.pkg,
|
|
|
|
sig: sig,
|
|
|
|
typ: nil,
|
|
|
|
name: v.Name(),
|
2015-08-04 13:51:41 +00:00
|
|
|
id: id + "_set",
|
2015-07-31 14:52:12 +00:00
|
|
|
doc: "sets " + g.pkg.Name() + "." + v.Name(),
|
|
|
|
ret: nil,
|
|
|
|
err: false,
|
|
|
|
}
|
|
|
|
g.genFunc(fset)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-27 16:47:18 +00:00
|
|
|
func (g *cpyGen) genPreamble() {
|
|
|
|
n := g.pkg.pkg.Name()
|
|
|
|
g.decl.Printf(cPreamble, n, g.pkg.pkg.Path(), filepath.Base(n))
|
2015-07-25 00:05:11 +00:00
|
|
|
}
|