Уведомления

Группа в Telegram: @pythonsu

#1 Июль 30, 2011 20:00:21

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

boost::python завернуть boost::array

Не получается по человечески завернуть массив фиксированной длины. Если кто делал поделитесь кодом.
Из мелочной любви к экономии решил в классе использовать

class Ta
{
public:
boost::array<float,3> x
};
хотел завернуть его както так:
    class_<std::vector<float> >("FloatVec")
.def(vector_indexing_suite<std::vector<float> >())
;
не хватает функций :( порезать vector_indexing_suite - както много получается работы

    class_<Tarr3>("Vec3")
.def("__getitem__",&(Tarr3::operator[]))
;
не проходит
c:\projects\rosa\reactormodels\rbt10\pointkin_dll.cpp(19): error C2780: ‘boost::python::class_<W> &boost::python::class_<W>::def(const char *,Fn,const A1 &,const A2 &,const A3 &)’ : expects 5 arguments - 2 provided
наверное надо ковыряться с перегрузкой operator

Получается сделать призводный класс и там все что надо прилепить
template<class T,int N>
class Tcv:public boost::array<T,N>
{
public:
T getitem(int i)const {return (*this)[i];}
void setitem(int i,const T& v){(*this)[i]=v;}
T len() const {return N;}
};

class_<TcvNC>("TcvNC")
.def("__getitem__",&TcvNC::getitem)
.def("__setitem__",&TcvNC::setitem)
.def("__len__",&TcvNC::len)
;
Но это мне кажется избыточным вмешательством в код.



Отредактировано (Июль 30, 2011 20:26:27)

Офлайн

#2 Авг. 1, 2011 22:42:51

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

boost::python завернуть boost::array

Оказалось проще прилепить функции с другими именами. Оно и полезнее когда раcширяешь функциональность данного класса

typedef boost::array<float,NC> Tarr6;

template<class T, int N>
struct _arrayN
{
typedef boost::array<T,N> arrayN;

static T get(arrayN const& self, int idx)
{
if( 0<=idx && idx<N ) return self[idx];
PyErr_SetString(PyExc_KeyError,"index out of range");
throw_error_already_set();
}

static boost::python::list getslice(arrayN const& self, int a,int b)
{
if(b>N){b=N;}
if(a<0){a=0;}
boost::python::list t;
for(int i=a;i<b;++i)
t.append(self[i]);
return t;
}
static void setslice(arrayN& self, int a,int b,boost::python::object& v)
{
if(b>N){b=N;}
if(a<0){a=0;}

for(int i=a;i<b;++i)
self[i]=extract<float>(v[i]);
}
static void set(arrayN& self, int idx, const T val) { self[idx]=val; }

static boost::python::list values(arrayN const& self)
{
boost::python::list t;
for(int i=0;i<N;++i)
t.append(self[i]);
return t;
}
static int size(arrayN const & self)
{
return NC;
}
};

BOOST_PYTHON_MODULE(rbt10)
{
class_<Tarr6>("Tarr6")
.def("__len__", &_arrayN<float,NC>::size)
.def("__getitem__",&_arrayN<float,NC>::get)
.def("__getslice__",&_arrayN<float,NC>::getslice)
.def("__setslice__",&_arrayN<float,NC>::setslice)
.def("__setitem__",&_arrayN<float,NC>::set)
;
}
Единственное - надо от __setslice__ перейти к setitem(slice,list)…



Отредактировано (Авг. 17, 2011 08:35:12)

Офлайн

#3 Авг. 16, 2011 22:54:10

Обедающий философ
От:
Зарегистрирован: 2011-05-06
Сообщения: 66
Репутация: +  0  -
Профиль   Отправить e-mail  

boost::python завернуть boost::array

А у меня обычные массивы не обёртываются.



Офлайн

#4 Авг. 17, 2011 08:36:55

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

boost::python завернуть boost::array

Везет вам. Может еще и sip попробовать? Он получше swig будет?



Офлайн

#5 Авг. 17, 2011 14:09:08

Обедающий философ
От:
Зарегистрирован: 2011-05-06
Сообщения: 66
Репутация: +  0  -
Профиль   Отправить e-mail  

boost::python завернуть boost::array

Это вы мне? Я же буст питон использую, согласно вашему же совету.

Вопщем, у меня не заворачиваются самые обычные массивы (скажем, int a;). Сколько ни искал - не смог ничего найти. Не поверю, что хвалёный буст для такого простого случая не может ничего предложить.

А теперь у меня ещё не заворачивается структура, точнее, вектор структур.

typedef bool (Agent::* action_func) () ;

struct pricelist {
action_func action;
real price;
};

............

class_< pricelist >("pricelist")
.def_readwrite("action", &pricelist::action)
.def_readwrite("price", &pricelist::price)
;

class_< vector <pricelist> >("action_vector")
.def(vector_indexing_suite< vector <pricelist> >())
;
На последнем определении вываливает кучу гумна в терминал.

А ещё у меня не обёртываются функции, возвращающие указатели (по крайней мере на объекты, остальные не пробовал).



Отредактировано (Авг. 17, 2011 14:57:15)

Офлайн

#6 Авг. 17, 2011 15:22:01

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

boost::python завернуть boost::array

Для векторов нужно использовать indexing suite: http://www.boost.org/doc/libs/1_47_0/libs/python/doc/v2/indexing.html
Для того, чтобы завернуть функцию, возвращающую указатель — нужно прописать return value policy, который расскажет как с этим указателем нужно поступать при decref.



Офлайн

#7 Авг. 17, 2011 16:44:51

Обедающий философ
От:
Зарегистрирован: 2011-05-06
Сообщения: 66
Репутация: +  0  -
Профиль   Отправить e-mail  

boost::python завернуть boost::array

А можно поподробнее? Хотя бы ссылки на примеры. Об return_value_policy вроде нашёл http://wiki.python.org/moin/boost.python/CallPolicy#return_value_policy.3CT.3E , однако там почему-то говорится, что reference_existing_object суть na&#239;ve (dangerous) approach, а какая ему альтернатива - я не понял.

Также у меня теперь указатели (и массивы соответственно) не понимаются питоном:

In [7]: a.outputs
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)

/media/3f16c67b-5e31-48bf-85c2-65bfd35e49f3/250gb/dima/alife/model/<ipython console> in <module>()

TypeError: No to_python (by-value) converter found for C++ type: float*

.........

In [44]: a.cell
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)

/media/3f16c67b-5e31-48bf-85c2-65bfd35e49f3/250gb/dima/alife/model/<ipython console> in <module>()

TypeError: No to_python (by-value) converter found for C++ type: Cell*
Я так понимаю, это всё одного поля петрушка. Но не понимаю, как с ней бороться. Можно было бы, конечно, всё на векторах переписать, но я не уверен, что это будет столь же быстро, к тому же, у меня некоторые массивы передаются в blas, а блас вроде как только массивы понимает.



Офлайн

#8 Авг. 17, 2011 18:14:14

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

boost::python завернуть boost::array

Правильно пишут. Что вы хотите увидеть? Есть метод Cell* meth();
Какое время жизни у Cell? Кто удаляет? Что будет, если вы куда-то этот Cell* присвоите?
Вектора не нужны — достаточно простого класса-обертки. Сколько элементов у float* (это вдогонку к предыдущим вопросам)?



Офлайн

#9 Авг. 17, 2011 21:09:08

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

boost::python завернуть boost::array

Ну у меня известно сколько элементов у float* - 3
Про indexing suite я наверное нечетко написал. Обычный sute заточен под наличие операций удаления элементов, а мой базовый тип boost::array<float,3> этого не умеет в принципе - он не контейнер он обеспечивает только доступ по индексу и слайсинг. Поэтому indexing suite валится(те не компилируется
).

Обедающий философ
Вопщем, у меня не заворачиваются самые обычные массивы
это потому float a и float* a; при передаче в функцию - почти одно и тоже.
Обедающий философ
А можно поподробнее?
Если надо пишите сюда или в личку могу полностью работающий пример прислать. Но int a я вам не смогу завернуть….



Офлайн

#10 Авг. 17, 2011 21:16:24

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

boost::python завернуть boost::array

doza_and, как раз с вашим примером все хорошо и ясно



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version