用于读取可变参数长度的 Python C 包装器
Posted
技术标签:
【中文标题】用于读取可变参数长度的 Python C 包装器【英文标题】:Python C wrapper for reading variable argument lengths 【发布时间】:2012-07-25 00:30:32 【问题描述】:我正在尝试替换 MATLAB/MEX 并切换到 Python。我遇到了 SWIG、ctypes 和 Cython 作为可能的解决方案,并开始尝试 SWIG(这看起来很简单)。
我的 C 函数具有 main(int argc, char *argv[])
形式的可变参数长度。我在网上找到了解决方案,但是与 SWIG 一起使用会导致很多问题。
-
其他方法(ctypes / Cython)是否更简单?
使用 SWIG 完成此任务的任何示例都会有所帮助。
【问题讨论】:
【参考方案1】:实际上有an example in the SWIG documentation 用于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[]);
足够了。
【讨论】:
谢谢,这个答案很完美!当我尝试使用@HYRY 的 ctypes 答案时,我会得到错误。是否可以使用 ctypes 代替 swig?我很好奇...:/ @BPL 你在sizeof(size_t) != sizeof(int)
的平台上吗?【参考方案2】:
这是一个使用 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))
【讨论】:
谢谢。但是,如果我对 .c 文件进行任何更改并尝试使用 python 代码,则此更改不会反映。我试图在你的代码末尾“del dll”,但这没有帮助。如何卸载此 dll?以上是关于用于读取可变参数长度的 Python C 包装器的主要内容,如果未能解决你的问题,请参考以下文章