Python - 类型图中的 SWIG 不起作用
Posted
技术标签:
【中文标题】Python - 类型图中的 SWIG 不起作用【英文标题】:Python - SWIG in typemap does not work 【发布时间】:2018-01-22 23:32:49 【问题描述】:我正在学习将c++代码包装成Python模块,像int foo(int argc, char **argv);
这样的函数需要typemap,比如一个简单的c++代码就可以
#include <iostream>
int foo(int argc, char** argv)
std::cout << "Have " << argc << " arguments:" << std::endl;
for (int i = 0; i < argc; ++i)
std::cout << argv[i] << std::endl;
return 0;
然后我按照 SWIG 教程here (34.9.2) 编写了 SWIG 的接口文件:
%module Args
%
extern int foo(int argc, char **argv);
%
%typemap(in) (int argc, char **argv)
/* Check if is a list */
if (PyList_Check($input))
int i;
$1 = PyList_Size($input);
$2 = (char **) malloc(($1+1)*sizeof(char *));
for (i = 0; i < $1; i++)
PyObject *o = PyList_GetItem($input,i);
if (PyString_Check(o))
$2[i] = PyString_AsString(PyList_GetItem($input,i));
else
PyErr_SetString(PyExc_TypeError,"list must contain strings");
free($2);
return NULL;
$2[i] = 0;
else
PyErr_SetString(PyExc_TypeError,"not a list");
return NULL;
%typemap(freearg) (int argc, char **argv)
free((char *) $2);
extern int foo(int argc, char **argv);
但是,在构建模块后,Python中总是出现错误:
>>> import Args
>>> Args.foo(["foo","bar","spam","1"])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list must contain strings
在类型图中,$input
似乎确实作为 Python 列表接收,但 PyList_GetItem($input,i)
出现问题。我是不是做错了什么?
提前致谢!
【问题讨论】:
水晶球在工作:这是 Python 3 吗? 是的。我使用 Python 3.6.1 【参考方案1】:字节与字符
根本问题是 Python 3 字符串是 character 字符串,而普通 Python 2 字符串和 char*
是 byte 字符串。 (char*
通常也被视为空终止。)因此,PyString_Check
已在 Python 3 中删除,您必须以某种方式处理编码。
如果您想接受 Python 3 str
对象,请使用 PyUnicode
函数来检查和编码参数。否则,从 Python 传递 bytes
对象:bytes literals 用于固定的 ASCII 字符串(如 Args.foo([b"foo",b"bar",b"spam",b"1"])
),否则为 str.encode
的结果。
代码编译的原因
SWIG 生成的包装器代码与Python 2 or 3 兼容。
即使使用 -py3
,它也是以 Python 2 风格编写的,由许多兼容性宏支持(来自 pyhead.swg
):
#if PY_VERSION_HEX >= 0x03000000
/* ... */
#define PyString_Check(name) PyBytes_Check(name)
/* ... */
#endif
在现代,主要是 3 世界中,SWIG 可能更喜欢使用bytesobject.h
。它以另一种方式定义同义词,使字节串明显。
【讨论】:
感谢您的出色解释。没有意识到 Python 3 的问题。将PyString
更改为PyUnicode_AsUTF8
确实有效!【参考方案2】:
我通过谷歌搜索发现了这个问题,我收到了同样的错误
TypeError: list must contain strings
由于该错误仅在升级到 Python 3 后出现,我能够通过以下更改解决它
Args.foo([b"foo",n"bar",b"spam",b"1"])
b
强制 Python 将字符串作为 Python2 字节字符串而不是 Python3 unicodes 字符串发送,以防万一这对其他人有帮助。
【讨论】:
以上是关于Python - 类型图中的 SWIG 不起作用的主要内容,如果未能解决你的问题,请参考以下文章