2013-05-08 119 views
6

一些SciPy函数(如scipy.ndimage.interpolation.geometric_transform)可以将指针指向C函数作为参数,以避免在输入数组的每个点上调用Python可调用函数。在Cython中创建一个PyCObject指针

简而言之:

  • 定义一个C模块
  • 返回一个PyCObject&my_function指针和(任选地)一个void*指针在称为my_function某处函数以绕过
一些全局数据

相关API方法是PyCObject_FromVoidPtrAndDesc,您可以阅读Extending ndimage in C以查看它的实际应用。

我对使用Cython保持我的代码更易于管理非常感兴趣,但我不确定我应该如何创建这样的对象。任何,呃,指针?

+2

+1只是指针笑话:-p – Will 2013-05-08 14:16:55

+0

这似乎是正确的做! :D – 2013-05-08 14:50:50

回答

1

只要做到在用Cython你会用C做同样的事情,直接调用PyCObject_FromVoidPtrAndDesc。以下是从您的链接移植到Cython的示例:

###### example.pyx ###### 

from libc.stdlib cimport malloc, free 
from cpython.cobject cimport PyCObject_FromVoidPtrAndDesc 

cdef int _shift_function(int *output_coordinates, double* input_coordinates, 
      int output_rank, int input_rank, double *shift_data): 
    cdef double shift = shift_data[0] 
    cdef int ii 
    for ii in range(input_rank): 
     input_coordinates[ii] = output_coordinates[ii] - shift 
    return 1 

cdef void _shift_destructor(void* cobject, void *shift_data): 
    free(shift_data) 

def shift_function(double shift): 
    """This is the function callable from python.""" 
    cdef double* shift_data = <double*>malloc(sizeof(shift)) 
    shift_data[0] = shift 
    return PyCObject_FromVoidPtrAndDesc(&_shift_function, 
             shift_data, 
             &_shift_destructor) 

性能应与纯C版本相同。

请注意,Cyhton要求运营商&获取函数地址。另外,Cython缺少指针取消引用运算符*,而是使用索引等价物(*ptr - >ptr[0])。

+0

感谢您的正确'cimport's!过了一段时间,我正在考虑从'.h'文件导入函数并做大致相同的操作,但我不确定如何处理引用和解除引用,因此您的示例将一次性清除它;) – 2013-05-09 21:20:14

0

我认为这是一个坏主意。 Cython是为了避免编写PyObjects而创建的!此外,在这种情况下,通过用Cython编写的代码可能不会提高代码的维护...... 无论如何,你可以在你用Cython代码

from cpython.ref cimport PyObject 

导入的PyObject。

UPDATE

from cpython cimport * 

更安全。

干杯, 达维德

+1

你可能注意到我写了**'PyCObject' **而不是'PyObject'。 “PyObject”是一个普通的Python对象,而“PyCObject”是一个特殊的“PyObject”,用于保存指向原始内存地址的不透明指针。正如我所说,它被SciPy中的一些函数使用,他们只是从'PyCObject'中检索函数指针并使用它,而没有调用真正的Python方法的开销。 ;) – 2013-05-08 19:03:00