Wrapping a function which returns a pointer to a python object with ctypes
I've got some code which comp开发者_运维技巧iles a C function to create a numpy generic function with it using PyUFunc_FromFuncAndData. I've written some cython to create the ufunc but I'd like to do it with ctypes if possible since I'm intending to distribute it and I'd like to avoid users the compile step.
The problem is that PyUFunc_FromFuncAndData returns a pointer to a PyObject. Is it possible to use it as an object from python code?
Basically, I'd like to be able to translate the following cython code to 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)
Set restype of that function to ctypes.py_object. The following example uses a call to python C-API but it works the same for anything else.
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"
精彩评论