Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用SWIG和Python/capi包装返回std::map的函数 我想包装一个C++例程,它返回一个 STD::MAP代码和C++类实例的指针。我很难让这个与SWIG一起工作,如果能提供任何帮助,我将不胜感激。我试图通过一个简单的例子将这个问题归结为它的本质_Python_C++_Swig - Fatal编程技术网

使用SWIG和Python/capi包装返回std::map的函数 我想包装一个C++例程,它返回一个 STD::MAP代码和C++类实例的指针。我很难让这个与SWIG一起工作,如果能提供任何帮助,我将不胜感激。我试图通过一个简单的例子将这个问题归结为它的本质

使用SWIG和Python/capi包装返回std::map的函数 我想包装一个C++例程,它返回一个 STD::MAP代码和C++类实例的指针。我很难让这个与SWIG一起工作,如果能提供任何帮助,我将不胜感激。我试图通过一个简单的例子将这个问题归结为它的本质,python,c++,swig,Python,C++,Swig,标题test.h定义如下: /* File test.h */ #include <stdlib.h> #include <stdio.h> #include <map> class Test { private: static int n; int id; public: Test(); void printId(); }; std::map<int, Test*> get_tests(int num_

标题
test.h
定义如下:

/* File test.h */
#include <stdlib.h>
#include <stdio.h>
#include <map>

class Test {
  private:
    static int n;
    int id;
  public:
    Test();
    void printId();
};

std::map<int, Test*> get_tests(int num_tests);
> 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
我已经编写了一个SWIG接口文件
test.I
,试图适应此例程,以便可以将
std::map
作为Python中的字典返回:

%module test

%{
  #define SWIG_FILE_WITH_INIT
  #include "test.h"
%}

%include <std_map.i>
%typemap(out) std::map<int, Test*> {

  $result = PyDict_New();
  int size = $1.size();

  std::map<int, Test*>::iterator iter;
  Test* test;
  int count;

  for (iter = $1.begin(); iter != $1.end(); ++iter) {
    count = iter->first;
    test = iter->second;
    PyDict_SetItem($result, PyInt_FromLong(count),           
      SWIG_NewPointerObj(SWIG_as_voidptr(test), SWIGTYPE_p_Test, SWIG_POINTER_NEW | 0));
  }
}

%include "test.h"
import test

tests = test.get_tests(3)
print tests

for test in tests.values():
  test.printId()
然后,我希望能够在Python中执行以下操作:

%module test

%{
  #define SWIG_FILE_WITH_INIT
  #include "test.h"
%}

%include <std_map.i>
%typemap(out) std::map<int, Test*> {

  $result = PyDict_New();
  int size = $1.size();

  std::map<int, Test*>::iterator iter;
  Test* test;
  int count;

  for (iter = $1.begin(); iter != $1.end(); ++iter) {
    count = iter->first;
    test = iter->second;
    PyDict_SetItem($result, PyInt_FromLong(count),           
      SWIG_NewPointerObj(SWIG_as_voidptr(test), SWIGTYPE_p_Test, SWIG_POINTER_NEW | 0));
  }
}

%include "test.h"
import test

tests = test.get_tests(3)
print tests

for test in tests.values():
  test.printId()
但是,如果将其作为脚本
example.py
运行,则会得到以下输出:

> python example.py 
{0: <Swig Object of type 'Test *' at 0x7f056a7327e0>, 1: <Swig Object of type 'Test *' at     
0x7f056a732750>, 2: <Swig Object of type 'Test *' at 0x7f056a7329f0>}
Traceback (most recent call last):
  File "example.py", line 8, in <module>
    test.printId()
AttributeError: 'SwigPyObject' object has no attribute 'printId'
>python example.py
{0: , 1: , 2: }
回溯(最近一次呼叫最后一次):
文件“example.py”,第8行,在
test.printId()
AttributeError:“SwigPyObject”对象没有属性“printId”

你知道为什么我将
SwigPyObject
实例作为输出,而不是
Test
的SWIG代理吗?任何帮助都将不胜感激

目前,您看到的问题是由SWIG提供的std_map.i中的默认行为引起的。它提供的类型映射试图合理地包装所有
std::map
用法

其中之一是干扰您自己的输出类型映射,因此如果我们将您的接口文件更改为:

%module test

%{
  #define SWIG_FILE_WITH_INIT
  #include "test.h"
%}

%include <std_map.i>
%clear std::map<int, Test*>;
%typemap(out) std::map<int, Test*> {

  $result = PyDict_New();
  int size = $1.size();

  std::map<int, Test*>::iterator iter;
  Test* test;
  int count;

  for (iter = $1.begin(); iter != $1.end(); ++iter) {
    count = iter->first;
    test = iter->second;
    PyObject *value = SWIG_NewPointerObj(SWIG_as_voidptr(test), SWIGTYPE_p_Test, 0);
    PyDict_SetItem($result, PyInt_FromLong(count), value);
  }
}

%include "test.h"
可能并没有实现您想要的功能—它将指针的所有权转移到Python,这意味着一旦Python代理完成,它将为您调用
delete
,并在地图中留下一个悬空的指针

您还可以使用
$descriptor
来避免必须找出SWIG的内部名称损坏方案,因此它变成:

// No ownership, lookup descriptor:
SWIG_NewPointerObj(SWIG_as_voidptr(test), $descriptor(Test*), 0);

作为一个附带问题-为什么地图上有
Test*
,而不仅仅是
Test
?奇妙的答案-刚才学到了很多。谢谢你发帖!