我正在使用SWIG为C库生成Python绑定。库使用值语义定义结构。在C++术语中,结构是POD -用^ {CD1}}复制它,产生一个语义正确的拷贝。
clib.h:
struct s
{
int i;
};
我使用SWIG将其编译成一个Python模块。有关构建过程的详细信息,请参见本问题的“附录”
在C代码中,我们可以验证struct类型变量的赋值运算符是否具有值语义:
#include <assert.h>
#include "clib.h"
int main()
{
struct s s1;
s1.i = 100;
struct s s2 = s1;
assert(s2.i == 100);
s2.i = 101;
assert(s1.i == 100);
}
正如预期的那样,在Python包装中,我们使用了引用语义:
import clib
s1 = clib.s()
s1.i = 100
s2 = s1
assert s2.i == 100
s2.i = 101
assert s1.i == 101
如果我们的库是用C++编写的,并且{{CD2}}有一个拷贝构造函数,SWIG也会为Python包装器生成一个(reference)。我们可以写:
s3 = clib.s(s1)
但对于C库,不会生成此包装:
TypeError: __init__() takes exactly 1 argument (2 given)
我们可能希望SWIG为copy.deepcopy
生成适当的魔术方法:
from copy import deepcopy
s4 = deepcopy(s1)
但它没有:
TypeError: can't pickle SwigPyObject objects
我很困惑。这看起来应该很简单,但我什么也找不到。在{a2}中,“复制”一词只出现在C++复制构造函数的先前链接的注释中,以及在生成的包装代码的一些低层次细节中。答案非常复杂
定义一个普通的SWIG接口文件clib.i
:
%module clib
%{
#include "clib.h"
%}
%include "clib.h"
使用setup.py
创建Python模块:
from distutils.core import setup, Extension
clib = Extension(
"_clib",
sources=["clib_wrap.c"],
extra_compile_args=["-g"],
)
setup(name="clib", version="1.0", ext_modules=[clib])
用Makefile
构建整个过程:
swig: setup.py clib_wrap.c
python2 setup.py build_ext --inplace
clib_wrap.c: clib.i
swig -python clib.i
然后,完全按照上面列出的方法编译/运行Python和C测试程序
虽然C库不能有构造函数/析构函数,但您可以在SWIG包装器ref: swig docs 5.5.6之后定义它们。注意,施工人员必须仔细书写:
测试一:
用例:
相关问题 更多 >
编程相关推荐