我正在尝试替换MATLAB / MEX并切换到Python。我遇到了SWIG,ctypes& Cython作为可能的解决方案并开始尝试SWIG(这看起来非常简单)。
我的C函数具有main(int argc, char *argv[])
形式的可变参数长度。我在网上找到了解决方案,但是使用SWIG可以解决很多问题。
答案 0 :(得分:5)
对于Python的这种功能,实际上an example in the SWIG documentation。我在这里引用了一个小小的改动:
%typemap(in) (int argc, char *argv[]) { int i; if (!PyList_Check($input)) { PyErr_SetString(PyExc_ValueError, "Expecting a list"); return NULL; } $1 = PyList_Size($input); $2 = (char **) malloc(($1+1)*sizeof(char *)); for (i = 0; i < $1; i++) { PyObject *s = PyList_GetItem($input,i); if (!PyString_Check(s)) { free($2); PyErr_SetString(PyExc_ValueError, "List items must be strings"); return NULL; } $2[i] = PyString_AsString(s); } $2[i] = 0; } %typemap(freearg) (int argc, char *argv[]) { free($2); // If here is uneeded, free(NULL) is legal }
这使您可以在Python中完成:
import test
test.foo(["a", "b", "c"])
其中test
是您为SWIG提供的模块的名称,foo
是与签名int argc, char *argv[]
匹配的函数。简单直观地用于Python程序员,它封装并重用了复杂的位。
文档似乎没有提到的是,有一个接口文件可以为您完成所有这些:
%module test
%include <argcargv.i>
%apply (int ARGC, char **ARGV) { (int argc, char *argv[]) }
void foo(int argc, char *argv[]);
就足够了。
答案 1 :(得分:0)
以下是使用ctypes的示例。
首先是c代码,它不能改变argv的内容:
#include <stdio.h>
void test(int n, char *argv[])
{
int i;
for(i=0;i<n;i++)
{
printf("%s\n", argv[i]);
}
}
然后你可以通过以下python代码调用这个c函数:
from ctypes import *
dll = cdll.LoadLibrary("charpp_test.dll")
argv = ["test1", "testtest2", "testtesttest3"]
dll.test(len(argv), (c_char_p*len(argv))(*argv))