使用ctypes包装返回Python对象指针的函数
我有一些代码,它可以把一个C语言的函数编译成一个numpy的通用函数,使用的是PyUFunc_FromFuncAndData。我写了一些cython代码来创建这个ufunc,但我想如果可以的话用ctypes来实现,因为我打算把它分发出去,希望用户不需要编译这一步。
问题是,PyUFunc_FromFuncAndData返回的是一个指向PyObject的指针。那我能不能在Python代码中把它当作一个对象来使用呢?
简单来说,我想把下面的cython代码转换成python/ctypes:
from numpy cimport NPY_DOUBLE
from libc.stdlib cimport malloc, free
cdef extern from "numpy/ufuncobject.h":
ctypedef void (*PyUFuncGenericFunction) (char **, Py_ssize_t *, Py_ssize_t *, void *)
object PyUFunc_FromFuncAndData (PyUFuncGenericFunction *, void **, char *, int, int, int, int, char *, char *, int)
void import_ufunc()
import_ufunc()
cdef class UFuncWrapper:
cdef readonly object func
cdef object _llvm_func
cdef PyUFuncGenericFunction function
cdef char *types
cdef bytes name
def __init__(self, func, ufunc, long long ptr):
self._llvm_func = ufunc # keep a ref to prevent it from being gced
cdef int num_args = len(func.args)
self.types = <char*>malloc(sizeof(char)*(num_args+1))
self.name = func.name
cdef int i
for i in range(num_args+1):
self.types[i] = NPY_DOUBLE
self.function = <PyUFuncGenericFunction>ptr
self.func = PyUFunc_FromFuncAndData(
&self.function,
NULL,
self.types,
1, #ntypes
num_args,
1,
-1, # PyUFunc_None,
self.name,
self.name, #FIXME: __doc__
0)
def __dealloc__(self):
free(self.types)
def __call__(self, *args):
return self.func(*args)
1 个回答
3
把那个函数的返回类型设置为ctypes.py_object。下面的例子使用了调用Python的C接口,但其他的情况也是一样的。
import ctypes
class Foo(object):
bar='baz'
foo=ctypes.py_object(Foo)
print 'Memory adress of Foo.bar object:',
print ctypes.pythonapi.PyObject_GetAttrString(foo,'bar') # prints the pointer
ctypes.pythonapi.PyObject_GetAttrString.restype = ctypes.py_object
print 'Actual Foo.bar after we set restype correctly:',
print ctypes.pythonapi.PyObject_GetAttrString(foo,'bar') # prints "baz"