这是我第一次遇到SWIG,我没有通过搜索找到任何有用的东西,这可能意味着我甚至没有找到正确的方向。如果有人能让我受到影响,那就太好了。
我有一个C函数,它将double *作为参数并将其用作输出:
int myFunc(double* p, int len){
int i;
for(i=0; i<len; i++){
p[i] = (double)i;
}
return 0;
}
为了包装它,我没有做任何棘手或自定义的事情,我只是让SWIG做它默认做的事情:
%module MyModule
%{
/* Includes the header in the wrapper code */
#include "MyModule.h"
%}
/* Parse the header file to generate wrappers */
%include "MyModule.h"
这一切都是因为它编译并构建了一个我可以加载的模块。但是,有人可能会合理地期望能够像这样从Python中调用它,而且我不能:
numbers = [0.0]*5
myFunc(numbers, 5)
SWIG抱怨第一个参数是错误的类型。我一直在阅读有关typemaps.i的内容,它允许您手动指定类型转换。对于像这个例子那样标准的东西,这是否必要?如果有人能告诉我应该阅读的内容或Google的内容,我将不胜感激。
答案 0 :(得分:0)
使用内置类型作为SWIG的输入参数会自动处理,但SWIG需要一些输出参数帮助。以下是一种简单的方法。
请注意,%inline
是一种在.i
文件中为其添加函数和SWIG包装的方法,而不是使用#include
和%include
生成头文件。对于小例子来说这很好。
参考:carrays.i
%module x
%include <carrays.i>
%array_functions(double,doubles)
%inline %{
int myFunc(double* p, int len)
{
int i;
for(i = 0; i < len; i++)
p[i] = (double)i;
return 0;
}
%}
输出:
>>> import x
>>> pd=x.new_doubles(10)
>>> pd
<Swig Object of type 'double *' at 0x0000000002235CC0>
>>> x.myFunc(pd,10)
0
>>> x.doubles_getitem(pd,0)
0.0
>>> x.doubles_getitem(pd,1)
1.0
>>> x.doubles_getitem(pd,9)
9.0
>>> x.delete_doubles(pd)
通过更多工作,我们可以使用类型映射获得更多Pythonic界面。下面是一组in / argout / argfree类型映射,从单个Python输入对象生成类型C参数。
%typemap(in)
定义了如何将Python输入转换为输入参数。它检查整数对象并生成第二个参数(len),然后使用malloc
生成第一个参数。
%typemap(argout)
定义了如何将输出参数转换为Python对象,并将其附加到由$result
表示的现有返回值。
%typemap(free)
从in
typemap中释放已分配的参数。
参考文献:Common typemap methods,Multi-argument typemaps
%module x
%include <exception.i>
%typemap(in) (double* p, int len) %{
if(!PyLong_Check($input))
SWIG_exception(SWIG_TypeError, "expected integer");
$2 = PyLong_AsUnsignedLong($input);
$1 = malloc($2 * sizeof(double));
%}
%typemap(freearg) (double* p, int len) %{
free($1);
%}
%typemap(argout) (double* p, int len) {
PyObject* list = PyList_New($2);
int i;
for(i = 0; i < $2; ++i)
PyList_SET_ITEM(list, i, PyFloat_FromDouble($1[i]));
$result = SWIG_Python_AppendOutput($result, list);
}
%inline %{
int myFunc(double * p, int len)
{
int i;
for(i = 0; i < len; i++)
p[i] = (double)i;
return 0;
}
%}
输出:
>>> import x
>>> x.myFunc(5)
[0, [0.0, 1.0, 2.0, 3.0, 4.0]]
>>> return_value, double_list = x.myFunc(3)
>>> return_value
0
>>> double_list
[0.0, 1.0, 2.0]