我在c中有一个全局变量数组,我想把它拉到python中。我在使用varout
类型图时遇到了困难:
/* example.c */
int foo[] = {0, 1};
这是一个非常普通的界面:
/* example.i */
%module example
%{
extern int foo[2];
%}
%typemap(varout) int foo[] {
int i;
//$1, $1_dim0, $1_dim1
$result = PyList_New($1_dim0);
for (i = 0; i < $1_dim0; i++) {
PyObject *o = PyInt_FromLong((double) $1[i]);
PyList_SetItem($result,i,o);
}
}
%include "example.c"
当我尝试用以下SConstruct构建它时:
import distutils.sysconfig
env = Environment(SWIGFLAGS='-python -shadow -Wall'.split(),
CPPPATH=[distutils.sysconfig.get_python_inc()],
SHLIBPREFIX="")
env.SharedLibrary('_example.so', ['example.c', 'example.i'])
$1_dim0
特殊变量未填充,导致example_wrap.c
中出现以下不可编译代码:
SWIGINTERN PyObject *Swig_var_foo_get(void) {
PyObject *pyobj = 0;
{
int i;
//foo, , foo_dim1
pyobj = PyList_New();
for (i = 0; i < ; i++) {
PyObject *o = PyInt_FromLong((double) foo[i]);
PyList_SetItem(pyobj,i,o);
}
}
return pyobj;
}
很明显,类型映射匹配已经发生,但数组的维度缺失。我错过了什么?对尺寸进行硬编码确实有效。
一般来说,有没有办法用swig扩展全局cvar
变量
$ swig -version
SWIG Version 2.0.4
Compiled with g++ [i686-pc-linux-gnu]
Configured options: +pcre
Please see http://www.swig.org for reporting bugs and further information
您的varout
类型映射即将实现。你需要做两个小改动:
-
您需要将尺寸
ANY
添加到int foo[]
类型映射:%typemap(varout) int foo[ANY] { int i; //$1, $1_dim0, $1_dim1 $result = PyList_New($1_dim0); for (i = 0; i < $1_dim0; i++) { PyObject *o = PyInt_FromLong((double) $1[i]); PyList_SetItem($result,i,o); } }
这可以确保您的类型映射与(任何)已知大小的数组匹配,而不仅仅等同于
int *foo
。 -
您需要修改example.c以使
foo
的大小更清晰。它是合法和正确的C,但除非你碰巧是一个完整的C编译器,否则很难推断数组的大小。更改为:int foo[2] = {0, 1};
足以确保它与CCD_ 10类型映射匹配。
有了这两个更改,生成的代码就如您所希望的那样工作:
SWIGINTERN PyObject *Swig_var_foo_get(void) {
PyObject *pyobj = 0;
{
int i;
//foo, 2, foo_dim1
pyobj = PyList_New(2);
for (i = 0; i < 2; i++) {
PyObject *o = PyInt_FromLong((double) foo[i]);
PyList_SetItem(pyobj,i,o);
}
}
return pyobj;
}
就是在我的机器上通过这些更改生成的内容。
对于像我这样思考如何处理非简单类型数组的人来说,这里有一种方法:
非简单类型:
typedef struct {
int a;
float b;
} Foo;
和一个全局阵列:
extern Foo *foov[40];
%typemap(varout) Foo *foov[ANY] {
int i;
$result = PyList_New($1_dim0);
for (i = 0; i < $1_dim0; i++) {
PyObject *o = SWIG_NewPointerObj($1[i], SWIGTYPE_p_Foo, 0);
PyList_SetItem($result, i, o);
}
}
刚刚分享了这篇文章,因为我花了很长时间才发现,这篇文章起到了帮助作用。只需要找出如何分配我的非简单类型的SWIG版本——发现它隐藏在这里:
http://www.swig.org/Doc2.0/Python.html#Python_nn64