Python SWIG: convert C++ return parameter to return value, and convert raw C++ type to Python type
我试图修改现有的Sigg Python接口的C++库,添加Python包装更多的功能,我将非常感谢一些帮助来自一些有经验的SWIG。
具体来说,我正在处理一个带有如下签名的函数:
1 | void execute(int x, double y, ResultType& result1, ResultType& result2); |
此函数接受两个空的resultType对象,并将其作为输出参数填充。在python中,这必须转换为只接受
resultType是一种在整个库中广泛使用的容器类型。
类型映射(in)从研究中,我认为我理解我需要为result1和result2添加一个类型映射"in",它吞没了参数并将它们保存到临时变量中。我还发现引用被swig转换成指针,因此
1 2 3 4 5 6 7 | typemap(in, numinputs=0) ResultType& result1 (ResultType temp) { $1 = &temp; } typemap(in, numinputs=0) ResultType& result2 (ResultType temp) { $1 = &temp; } |
打字机(AGOUT)
接下来,我添加了一个类型映射"argout",它将值附加到返回元组:
1 2 3 4 5 6 7 | %typemap(argout) ResultType& result1 { $result = SWIG_Python_AppendOutput($result, temp$argnum); } %typemap(argout) ResultType& result2 { $result = SWIG_Python_AppendOutput($result, temp$argnum); } |
但是,这显然是行不通的,因为EDCOX1×6将是原始的C++类型EDCOX1×7,而我需要有一个EDCOX1×8,以便追加到元组。结果类型已经有一个有效的swig包装。所以,在python中,我可以调用
就像$ 1是对输入类型映射中的Python输入对象的引用,1美元是对AdOutType映射中C++输出变量的引用。使用它,您可以为该数据生成一个python对象并将其附加到结果中。
以下是Windows的一个功能示例:
测试h
1 2 3 4 5 6 7 8 9 10 11 12 13 | #ifdef EXPORT #define API __declspec(dllexport) #else #define API __declspec(dllimport) #endif struct ResultType { int x; double y; }; API void execute(int x, double y, ResultType& result1, ResultType& result2); |
测试程序
1 2 3 4 5 6 7 8 9 10 | #define EXPORT #include"test.h" API void execute(int x, double y, ResultType& result1, ResultType& result2) { result1.x = 2 * x; result1.y = 2 * y; result2.x = 3 * x; result2.y = 3 * y; } |
试验。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | %module test %{ #include"test.h" %} %include <windows.i> %typemap(in,numinputs=0) ResultType& %{ // Create a persistent object to hold the result; $1 = new ResultType; %} %typemap(argout) ResultType& (PyObject* tmp) %{ // Store the persistent object in a PyObject* that will be destroyed // when it goes out of scope. tmp = SWIG_NewPointerObj($1, $1_descriptor, SWIG_POINTER_OWN); $result = SWIG_Python_AppendOutput($result, tmp); %} %include"test.h" |
产量
1 2 3 4 5 6 7 8 9 10 | >>> import test >>> r = test.execute(2,3) >>> r[0].x 4 >>> r[0].y 6.0 >>> r[1].x 6 >>> r[1].y 9.0 |