繁体   English   中英

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

[英]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

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

我认为问题出在试图将PyObject o直接转换为Test * 我们不希望作为SwigPyObjectPyObject的指针,而是在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM