SWIG-обернутый вектор векторов (C ++ to python) – как распознать внутренний вектор как прокси-объект?

Я столкнулся с аналогичной проблемой для Wrap std :: vector std :: vectors, C ++ SWIG Python – но это не просто простой синтаксический анализ на C ++. В моем коде на C ++ есть следующее:

namespace ns { typedef unsigned long long uint64_t; typedef std::vector<uint64_t> Vector; typedef std::vector<Vector> VectorOfVectors; class MyClass { /// ... /// Returns a reference to the internal vector allocated in C++ land const VectorOfVectors &GetVectors() const; }; } 

И в обертке SWIG

 %module myswig // ... %template(Uint64V) std::vector<ns::uint64_t>; %template(VUint64V) std::vector<std::vector<ns::uint64_t> >; 

Таким образом, обертка отлично работает, включая класс, и я могу получить вектор векторов класса:

 import myswig m = myswig.MyClass() v = m.GetVectors() print v 

Что дает мне:

 <myswig.VUint64V; proxy of <Swig Object of type 'std::vector< std::vector< ns::uint64_t,std::allocator< ns::uint64_t > > > *' at 0x994a050> > 

Но если я получаю доступ к элементу в векторе, я не получаю прокси-сервер, который является myswig.Uint64V – и это моя проблема.

 x = v[0] print x 

Я бы надеялся получить:

 <myswig.Uint64V; proxy of <Swig Object of type 'std::vector< ns::uint64_t, std::allocator< ns::uint64_t > > *' at 0x994a080> > 

Вместо этого я получаю:

 (<Swig Object of type 'ns::uint64_t *' at 0x994a080>, <Swig Object of type 'ns::uint64_t *' at 0x994a098>) 

То есть, индекс в векторе векторов дает мне 2-вставной кортеж, а не прокси-сервер для нужного мне векторного класса (так что доступ к внутреннему вектору так же просто, как доступ к другим векторам).

Я также получаю предупреждение:

 swig/python detected a memory leak of type 'ns::uint64_t *', no destructor found. 

потому что, конечно, для этого типа не существует деструктора.

Есть идеи?

  • Передача списка Python на вектор C ++ с использованием Boost.python
  • массив numpy C api
  • Как создать пустой вектор R для добавления новых элементов
  • python + maya: Повернуть ось Y вдоль вектора
  • SWIG-упаковка C ++ для Python: перевод списка строк в вектор STL строк STL
  • Граница решения границы matplotlib
  • Python numpy: преобразовать строку в массив numpy
  • Wrap std :: вектор std :: векторов, C ++ SWIG Python
  • One Solution collect form web for “SWIG-обернутый вектор векторов (C ++ to python) – как распознать внутренний вектор как прокси-объект?”

    Я работал над этим с моим коллегой, и нам удалось найти некоторые решения.

    Прежде всего, в файле SWIG .i важно определить эту переменную препроцессора:

     %{ # define SWIG_PYTHON_EXTRA_NATIVE_CONTAINERS %} 

    И затем, чтобы гарантировать, что ссылки, возвращаемые такими методами, как front (), back (), operator [] и т. Д., Фактически отображаются на правильный тип прокси для внутреннего вектора, следующие справки по типам:

     // In pop() %typemap(out) std::vector<std::vector<ns::uint64_t> >::value_type { $result = SWIG_NewPointerObj(SWIG_as_voidptr(&$1), $descriptor(std::vector<ns::uint64_t>), 0 | 0 ); } // In front(), back(), __getitem__() %typemap(out) std::vector<std::vector<ns::uint64_t> >::value_type & { $result = SWIG_NewPointerObj(SWIG_as_voidptr($1), $descriptor(std::vector<ns::uint64_t>), 0 | 0 ); } 

    Мы также обнаружили, что если вы хотите, чтобы ns :: uint64_t рассматривался как длинная переменная python (эквивалентная длинной длине без знака C), необходимо было еще несколько типов typemaps для обеспечения того, чтобы векторные методы, использующие значения и ссылки, вместо этого использовали только 64 -битные целочисленные значения.

     // In __getitem__() %typemap(out) ns::uint64_t { $result = PyLong_FromUnsignedLongLong($1); } // Not used (but probably useful to have, just in case) %typemap(in) ns::uint64_t { $1 = PyLong_AsUnsignedLongLong($input); } // In pop() %typemap(out) std::vector<ns::uint64_t>::value_type { $result = PyLong_FromUnsignedLongLong($1); } // In __getitem__(), front(), back() %typemap(out) std::vector<ns::uint64_t>::value_type & { $result = PyLong_FromUnsignedLongLong(*$1); } // In __setitem__(), append(), new Uint64Vector, push_back(), assign(), resize(), insert() // This allows a python long literal number to be used as a parameter to the above methods. // Note the use of a local variable declared at the SWIG wrapper function scope, // by placing the variable declaration in parentheses () prior to the open brace { %typemap(in) std::vector<ns::uint64_t>::value_type & (std::vector<ns::uint64_t>::value_type temp) { temp = PyLong_AsUnsignedLongLong($input); $1 = &temp; } 

    Надеюсь, это решение поможет людям в будущем!

    Python - лучший язык программирования в мире.