Сделать массив объектов C ++ повторяемым в Python - PullRequest
4 голосов
/ 17 января 2012

Я искал в Интернете и не добился успеха. Я оборачиваю приведенный ниже пример кода в 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 ]

2 голосов
/ 17 января 2012

Из вашего вопроса немного неясно, хотите ли вы использовать 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;
}

Вы можете обернуть его в %template, pyabc.i и std_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, я привел подробный пример впредыдущий ответ.

1 голос
/ 17 января 2012

Вы можете решить эту проблему на стороне 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)
0 голосов
/ 17 января 2012

Подход, аналогичный 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)

Это должно быть проще для вставки в файл SWIG с использованием директив %extend и %pythoncode.

Кроме того, SWIG имеет упаковщики для контейнеров STL , поэтому, возможно, используя их, вы легко сможете получить необходимые средства получения предметов.

...