Как передать указатель на массив в Python для обернутой функции C ++ - PullRequest
4 голосов
/ 02 июня 2009

Я новичок в программировании на C ++ / Python на разных языках и не очень разбираюсь в Python / C API. Я только начал использовать Boost.Python, чтобы обернуть библиотеку C ++ для Python. Я застрял в обертке функции, которая принимает указатель на массив в качестве аргумента. Следующий (2-й ctor) является его прототипом на C ++.

class AAF{
  AAF(AAF_TYPE t);
  AAF(double v0, const double * t1, const unsigned * t2, unsigned T);
  ~AAF();
}

Я правильно делаю, оборачивая это в boost :: python?

class_<AAF>("AAF", init<AAF_TYPE>())
  .def(init<double, const double*, const unsigned*, unsigned>());

Обратите внимание, что он успешно скомпилирован и связан, но я не мог понять, как его вызвать в Python. Моя наивная попытка, как следующая неудача.

>>> z = AAF(10, [4, 5.5, 10], [1, 1, 2], 3);

Traceback (most recent call last):
  File "./test_interval.py", line 40, in <module>
    z = AAF(10, [4, 5.5, 10], [1, 1, 2], 3);
Boost.Python.ArgumentError: Python argument types in
    AAF.__init__(AAF, int, list, list, int)
did not match C++ signature:
    __init__(_object*, AAF_TYPE)
    __init__(_object*, double, double const*, unsigned int const*, unsigned int)

>>> t1 = array.array('d', [4, 5.5, 10])
>>> t2 = array.array('I', [1, 1, 2])
>>> z = AAF(10, t1, t2, 3);

Traceback (most recent call last):
  File "./test_interval.py", line 40, in <module>
    z = AAF(10, t1, t2, 3);
Boost.Python.ArgumentError: Python argument types in
    AAF.__init__(AAF, int, array.array, array.array, int)
did not match C++ signature:
    __init__(_object*, AAF_TYPE)
    __init__(_object*, double, double const*, unsigned int const*, unsigned int)

Мой второй вопрос: мне также нужно обернуть деструктор? Пожалуйста, укажите, может ли это быть необходимо в некоторых случаях, но не всегда.

1 Ответ

4 голосов
/ 02 июня 2009

Упаковка правильная (в принципе) но в

AAF(10, [4, 5.5, 10], [1, 1, 2], 3);

(как указывает интерпретатор) вы передаете объектам списка функций Python, а не указателям.

Короче говоря, если ваша функция должна работать только со списками python, вам нужно изменить код для использования этого интерфейса (вместо использования указателей). Если вам нужно сохранить этот интерфейс, вы должны написать функцию-обертку, которая берет список из python, выполняет правильное преобразование и вызывает вашу оригинальную функцию c ++. То же самое относится к массивам numpy.

Обратите внимание, что boost :: python предлагает некоторый встроенный механизм для преобразования контейнеров python в stl-совместимые контейнеры.

Примером кода переноса для вашего дела может быть

void f(list o) {
    std::size_t n = len(o);
    double* tmp = new double[n];
    for (int i = 0; i < n; i++) {
        tmp[i] = extract<double>(o[i]);
    }
    std::cout << std::endl;
    // use tmp
    delete tmp;
}

Пожалуйста, ознакомьтесь с руководством по boost.python по адресу http://www.boost.org/doc/libs/1_39_0/libs/python/doc/tutorial/doc/html/index.html.

...