Использование Cython, чтобы обернуть библиотеку, которая оборачивает другую библиотеку - PullRequest
1 голос
/ 24 мая 2011

Моя цель - использовать Cython, чтобы обернуть библиотеку Apohenia , библиотеку C для научных вычислений.

Это попытка не восстановить колесо, и сама Апофения пытается сделать то же самое, основывая свои структуры на структурах из Научной библиотеки GNU:

typedef struct {
  gsl_vector *vector;
  gsl_matrix *matrix;
  gsl_vector *weights;
  apop_names *names;
  ...
} apop_data;

Apophenia предоставляет множество векторных / матричных операций, которые GSL либо не предоставляет, либо предоставляет немного неловко, но если GSL имеет функцию, нет смысла переписывать ее. Вы должны быть в состоянии писать код на C, который перемещается между набором apop_data в целом и его частями GSL так часто, как это необходимо, например ::

apop_data *dataset = apop_text_to_data("infile.csv"); //fill the matrix element
gsl_vector *minv = apop_matrix_inverse(dataset->matrix);
apop_data *dinv = apop_matrix_to_data(minv);
apop_data *identity_matrix = apop_dot(dataset, dinv); // I = D * D^-1
dataset->vector = gsl_vector_alloc(10);
gsl_vector_set_all(dataset->vector, 1);

Я не уверен, как обернуть это в Cython. Типичный метод, по-видимому, заключается в предоставлении структуры на стороне Python, включающей внутреннюю копию обертываемой структуры C:

"""I'm omitting the Cython declarations of the C structs and functions,
 which are just translations of the C declarations. Let those be in c_apop."""

cdef class apop_data:
   cdef c_apop.apop_data *d

   def set(self, row, col, val):
       c_apop.apop_data_set(self.d, row, col, val)

   def get(self, row, col):
       c_apop.apop_data_get(self.d, row, col)

   [et cetera]


cdef class gsl_vector:
   cdef c_apop.gsl_vector *v

   def set(self, row, val):
       c_apop.gsl_vector_set(self.v, row)

   def get(self, row):
       c_apop.gsl_vector_get(self.v, row)

   [et cetera]

Но теперь мы застряли, потому что если бы мы получили элемент вектора из набора данных,

 pyd = apop_data(10)
 v = pyd.d.vector

v - это необработанный C gsl_vector, а не объект Python, поэтому следующая строка не может быть v.get(0) или v.set(0, 1).

Мы могли бы добавить методы к классу apop_data с именами vector_get и vector_set, которые будут возвращать gsl_vector, заключенный в python, но это создает свои собственные проблемы: если пользователь перераспределяет вектор C, лежащий в основе py -вектор из pyv = pyd.get_vector(), как мы можем гарантировать, что pyd.d.vector будет перераспределен с ним?

Я попробовал пару вещей, и я чувствую, что теряю смысл каждый раз. Любые предложения о том, как лучше проектировать классы Cython для этой ситуации?

1 Ответ

0 голосов
/ 24 мая 2011

Структура C никогда не должна быть выставлена ​​стороне питона. Я быстро взглянул на библиотеку и, похоже, не нашел ничего необычного.

Единственная ситуация, которую вы должны отслеживать, это когда библиотека фактически перераспределяет базовый вектор. Эти функции обычно требуют указатель на указатель и обновляют значение указателя до новой выделенной структуры.

Зачем вам нужно выставить pyd.get_vector?

...