我想包装一个C ++例程,它接受一个类实例数组。我无法与SWIG合作,并希望能提供任何帮助。我试图通过一个简单的例子将这个问题归结为其本质。
标题test.h
定义如下:
/* File test.h */
#include <stdlib.h>
#include <stdio.h>
class Test {
private:
int my_value;
public:
Test(int value);
void printTest();
};
void print_tests(int num_tests, Test** tests);
实施在test.cpp
下面定义:
/* File test.cpp */
#include "test.h"
void print_tests(int num_tests, Test** tests) {
for (int i=0; i < num_tests; i++)
tests[i]->printTest();
}
Test::Test(int value) {
my_value = value;
}
void Test::printTest() {
printf("my value is %d\n", my_value);
}
我编写了一个SWIG接口文件test.i
来尝试容纳此例程,以便我可以传入Test
类实例的Python列表:
%module test
%{
#define SWIG_FILE_WITH_INIT
#include "test.h"
%}
%typemap(in) (int num_tests, Test** tests) {
if (!PyList_Check($input)) {
PyErr_SetString(PyExc_ValueError, "Expected a Python list of Tests");
return NULL;
}
$1 = PySequence_Length($input); // num_tests
$2 = (Test**) malloc(($1) * sizeof(Test*)); // tests
/* Loop over tests */
for (int i = 0; i < $1; i++) {
/* Extract the value from the list at this location */
PyObject* o = PyList_GetItem($input,i);
$2[i] = (Test*) o;
}
}
%include "test.h"
我打包例程并编译SWIG生成的包装器代码,并将其作为共享库链接,如下所示:
> swig -python -c++ -o test_wrap.cpp test.i
> gcc -c test.cpp -o test.o -fpic -std=c++0x
> gcc -I/usr/include/python2.7 -c test_wrap.cpp -o test_wrap.o -fpic -std=c++0x
> g++ test_wrap.o test.o -o _test.so -shared -Wl,-soname,_test.so
然后我希望能够在Python中执行以下操作:
import test
test1 = test.Test(2)
test2 = test.Test(1)
test.print_tests([test1, test2, test1])
但是,如果我将其作为脚本example.py
运行,我会收到以下输出:
> python example.py
my value is 3
my value is 2
my value is 3
为什么我将2
和3
作为输出,而不是分配给1
类构造函数的2
和Test
?我相信这是我的SWIG接口文件传递指向SWIG Test
类包装器实例而不是C ++ Test
类实例的指针的问题,但我不确定。任何帮助将不胜感激!
答案 0 :(得分:0)
我认为问题在于尝试直接将PyObject o
转换为Test *
。
我们不希望PyObject
的指针是SwigPyObject
,而Test*
指针位于SwigPyObject
内的某个位置。
你可以做的是重用SWIG_ConvertPtr
(swig在生成的包装器中的方式):
%typemap(in) (int num_tests, Test** tests) {
if (!PyList_Check($input)) {
PyErr_SetString(PyExc_ValueError, "Expected a Python list of Tests");
return NULL;
}
$1 = PySequence_Length($input); // num_tests
$2 = (Test**) malloc(($1) * sizeof(Test*)); // tests
/* Loop over tests */
for (int i = 0; i < $1; i++) {
/* Extract the value from the list at this location */
PyObject* o = PyList_GetItem($input,i);
void *p1 = 0;
SWIG_ConvertPtr(o, &p1,SWIGTYPE_p_Test, 0 | 0 );
$2[i] = (Test*) p1;
}
}