![](/img/trans.png)
[英]How to wrap a c++ function which takes in a function pointer in python using SWIG
[英]Using SWIG and the Python/C API to wrap a function which takes a Python list of C++ class instances
我想包装一个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
运行, example.py
得到以下输出:
> python example.py
my value is 3
my value is 2
my value is 3
有什么想法为什么我得到2
和3
作为输出,而不是分配给Test
类构造函数的1
和2
? 我相信这是我的SWIG接口文件传递指向SWIG Test
类包装实例而不是C ++ Test
类实例的指针的问题,但我不确定。 任何帮助将不胜感激!
我认为问题出在试图将PyObject o
直接转换为Test *
。 我们不希望作为SwigPyObject
的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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.