Моя цель - использовать 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 для этой ситуации?