gpt4 book ai didi

python - 使用 SWIG 和 Python/C API 包装一个函数,该函数采用 C++ 类实例的 Python 列表

转载 作者:太空宇宙 更新时间:2023-11-04 13:45:18 25 4
gpt4 key购买 nike

我想包装一个接受类实例数组的 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 接口(interface)文件 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

为什么我得到 23 作为输出,而不是 12分配给 Test 类构造函数?我认为这是我的 SWIG 接口(interface)文件传递指向 SWIG Test 类包装器实例而不是 C++ Test 类实例的指针的问题,但我不确定。任何帮助将不胜感激!

最佳答案

我认为问题在于尝试将 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;
}
}

关于python - 使用 SWIG 和 Python/C API 包装一个函数,该函数采用 C++ 类实例的 Python 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26276029/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com