2011-05-24 83 views
1

我的目标是使用Cython打包Apohenia库,一个用于科学计算的C库。使用Cython打包一个包装另一个库的库

这是为了不重新发明轮子,和Apophenia本身试图通过立足于那些由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,而不是一个蟒对象,所以下一行不能v.get(0)v.set(0, 1)

我们可以添加方法来命名vector_getvector_setapop_data类,将返回一个python包裹gsl_vector,但创建自己的问题:如果用户重新分配C载体的PY-矢量从pyv = pyd.get_vector()底层,怎么办我们保证pyd.d.vector与它重新分配?

我试过了几件事情,我觉得我每次都错过了这一点。有关如何为这种情况设计最佳Cython类的建议?

回答

0

C结构不应该暴露在python端。 我快速浏览了一下图书​​馆,似乎没有什么不寻常的东西。

唯一需要跟踪的情况是库实际重新分配底层向量。这些函数通常需要指向指针的指针,并将指针值更新为新分配的结构。

为什么你需要暴露pyd.get_vector?