包装一个函数,该函数返回指向具有ctypes的python对象的指针

包装一个函数,该函数返回指向具有ctypes的python对象的指针,python,numpy,ctypes,cython,Python,Numpy,Ctypes,Cython,我有一些代码,它编译了一个C函数,使用PyUFunc_FromFuncAndData创建一个numpy泛型函数。我已经写了一些cython来创建ufunc,但是如果可能的话,我想用ctypes来实现,因为我打算分发它,并且我想避免用户执行编译步骤 问题是PyUFunc_FromFuncAndData返回指向PyObject的指针。是否可以将其用作python代码中的对象 基本上,我希望能够将以下cython代码转换为python/ctypes: from numpy cimport NPY_DO

我有一些代码,它编译了一个C函数,使用PyUFunc_FromFuncAndData创建一个numpy泛型函数。我已经写了一些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)
来自numpy cimport NPY\u DOUBLE
来自libc.stdlib cimport malloc,免费
“numpy/ufunobject.h”中的cdef外部:
ctypedef void(*PyUFuncGenericFunction)(char**,Py_-ssize\u t*,Py_-ssize\u t*,void*)
对象PyUFunc_FromFuncAndData(PyUFuncGenericFunction*,void**,char*,int,int,int,int,char*,char*,int)
无效导入_ufunc()
import_ufunc()
cdef类UFuncWrapper:
cdef只读对象函数
cdef对象_llvm_func
cdef PyUFuncGenericFunction函数
cdef char*类型
cdef字节名称
定义初始化(self、func、ufunc、long-long ptr):
self._llvm_func=ufunc#保留一个ref以防止它被gced
cdef int num_args=len(函数args)
self.types=malloc(sizeof(char)*(num_args+1))
self.name=func.name
cdef int i
对于范围内的i(num_args+1):
self.types[i]=NPY\u DOUBLE
self.function=ptr
self.func=PyUFunc_FromFuncAndData(
&自我功能,
无效的
自我类型,
1#个
num_args,
1.
-1、#PyUFunc#u None、,
姓名,
self.name,#FIXME:u doc__
0)
def uu dealoc uu(自我):
自由(自我类型)
定义调用(self,*args):
返回self.func(*args)

将该函数的重新类型设置为ctypes.py\u对象。下面的示例使用了对PythonC-API的调用,但对其他任何操作都是一样的

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"

我猜您已经尝试过obvoius——将函数的
.restype
属性设置为
ctypes.POINTER(ctypes.py_对象)
,然后使用
返回的\u指针[0]
取消引用?