0

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

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

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

2 回答 2

6

在 SWIG 文档中实际上有一个示例,用于使用 Python 实现这种功能。我在这里引用了它,并做了一个小的改动:

%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[]);

足够了。

于 2012-07-25T08:58:06.933 回答
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))
于 2012-07-25T01:02:05.583 回答