用于读取变量参数长度的Python C包装器

时间:2012-07-25 00:30:33

标签: python swig ctypes cython wrapping

我正在尝试替换MATLAB / MEX并切换到Python。我遇到了SWIG,ctypes& Cython作为可能的解决方案并开始尝试SWIG(这看起来非常简单)。

我的C函数具有main(int argc, char *argv[])形式的可变参数长度。我在网上找到了解决方案,但是使用SWIG可以解决很多问题。

  1. 其他方法(ctypes / Cython)是否更简单?
  2. 使用SWIG执行此任务的任何示例都会有所帮助。

2 个答案:

答案 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))