使Python中的C ++对象数组可迭代

时间:2012-01-17 14:59:46

标签: c++ python arrays object swig

我在网上搜索过但没有成功。我将下面的示例代码包装到Python中(使用SWIG):

class atomo {
public:
    int i;
    atomo(int a) {
        i = a;
    };      
};

class funa {
public:
    atomo *lista[3];

    funa() {
        lista[0] = new atomo(1);
        lista[1] = new atomo(2);
        lista[2] = new atomo(3);
    };
};

但Python不能使用命令迭代或访问lista

>>> test = myModule.funa()
>>> test.lista[0]
      Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 6, in __iter__
      TypeError: 'SwigPyObject' object is not subscriptable

>>> for i in test.lista:
>>>     print(i)
      Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 6, in __iter__
      TypeError: 'SwigPyObject' object is not subscriptable

如何使lista可迭代?有一种方法可以使用Python列表而不是C ++数组吗?

我的Python版本是3.2,我使用SWIG 2.0.4和g ++ 4.6.1

谢谢

3 个答案:

答案 0 :(得分:2)

如果你想使用std::vector或你自己的数组,你的问题有点不清楚。

对于std::vector,给出一些C ++,如:

#include <vector>
#include <string>

struct foo {
  std::string name;
};

inline std::vector<foo> test() {
  std::vector<foo> ret;
  foo instance;
  instance.name = "one";
  ret.push_back(instance);
  instance.name = "two";
  ret.push_back(instance);
  return ret;
}

您可以使用%templatepyabc.istd_vector.i包裹它,例如:

%module test

%{
#include "test.h"
%}

%include "pyabc.i"
%include "std_vector.i"

%include "test.h"

%template (FooVector) std::vector<foo>;

将在Python类型上直观地表现。您需要使用以下内容调用SWIG:

swig -python -c++ -py3 -extranative test.i

如果想要将“自定义”容器包装成在Python端直观地表现,我在之前的答案中给出了detailed example

答案 1 :(得分:1)

为简单起见,您可能希望在Python端而不是C ++ / SWIG端解决此问题。

# wrapper/facade
class Funa:
    def __init__(self):
        self._impl = myModule.funa()   # _impl => implementation

    def __iter__(self):
        for i in xrange(3):
            yield self._impl.lista[i]

test = Funa()
for x in test:
    print(x)

答案 2 :(得分:0)

larsmans的类似方法是让Funa.__iter__返回生成器对象。然后你只需要添加到SWIG创建的界面。 (通过他的包装,你必须包装所有其他方法,或者玩__getattr__。)大致就是这样的

class Funa:

  class FunaIter :
    def __init__(self, parent) :
      self.parent = parent
      self.pos = 0

    def __iter__(self) :
      while self.pos < 3 :
        yield self.parent.lista[self.pos]
        self.pos += 1

  def __iter__(self) :
    return self.FunaIter(self)

使用%extend%pythoncode指令插入SWIG文件应该更简单。

此外,SWIG has wrappers for STL containers,也许使用这些,您可以轻松获得必要的项目获取者。