У мене є невеликий проект, який чудово працює з SWIG. Зокрема, деякі мої функції повертають std::vector
s, які перекладаються на кортежі в Python. Зараз я роблю багато цифр, тому у мене просто SWIG перетворює їх у масиви numpy після їх повернення з коду c ++. Для цього я використовую щось на зразок наступного в SWIG.
%feature("pythonappend") My::Cool::Namespace::Data() const %{ if isinstance(val, tuple) : val = numpy.array(val) %}
(Насправді є кілька функцій з іменем Data, деякі з яких повертаються з плаваючою здатністю, тому я перевіряю, що val
це насправді кортеж.) Це працює просто чудово.
Але я також хотів би використовувати -builtin
прапор, який зараз доступний. Дзвінки до цих функцій Data є рідкісними та в основному інтерактивними, тому їх повільність не є проблемою, але є й інші повільні цикли, які значно пришвидшуються завдяки вбудованій опції.
Проблема полягає в тому, що коли я використовую цей прапор, функція pythonappend мовчки ігнорується. Тепер Data просто повертає кортеж знову. Чи можна якось повернути масиви numpy? Я спробував скористатися друкарськими картами, але це перетворилося на гігантський безлад.
Редагувати:
Бореалід дуже красиво відповів на запитання. Тільки для повноти, я включаю пару пов’язаних, але тонко різних карт набору, які мені потрібні, тому що я повертаюся за посиланням const і використовую вектори векторів (не запускати!). Вони досить різні, і я не хотів би, щоб хтось ще спотикався, намагаючись з’ясувати незначні відмінності.
%typemap(out) std::vector<int>& {
npy_intp result_size = $1->size();
npy_intp dims[1] = { result_size };
PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(1, dims, NPY_INT);
int* dat = (int*) PyArray_DATA(npy_arr);
for (size_t i = 0; i < result_size; ++i) { dat[i] = (*$1)[i]; }
$result = PyArray_Return(npy_arr);
}
%typemap(out) std::vector<std::vector<int> >& {
npy_intp result_size = $1->size();
npy_intp result_size2 = (result_size>0 ? (*$1)[0].size() : 0);
npy_intp dims[2] = { result_size, result_size2 };
PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_INT);
int* dat = (int*) PyArray_DATA(npy_arr);
for (size_t i = 0; i < result_size; ++i) { for (size_t j = 0; j < result_size2; ++j) { dat[i*result_size2+j] = (*$1)[i][j]; } }
$result = PyArray_Return(npy_arr);
}
Редагувати 2:
Хоча не зовсім те, що я шукав, подібні проблеми також можуть бути вирішені за допомогою підходу @ MONK ( пояснення тут ).