问题
I have a function with void *
parameter and I want to store it in the dict.
What I do is:
%%cython
cdef void foo(void * bar):
pass
cdef dict foobar = {'foo': foo}
But this code raises an Error: Cannot convert 'void (void *)' to Python object
Any ways to overcome this problem?
回答1:
The easiest solution is to create a cdef class
that can wrap this function. Since the cdef class
is a Python object it can be stored in a dictionary like any other Python object.
ctypedef void (*void_func_ptr)(void*)
cdef class VoidFuncWrapper:
cdef void_func_ptr func
def __cinit__(self):
self.func = NULL
@staticmethod
cdef VoidFuncWrapper make_from_ptr(void_func_ptr f):
cdef VoidFuncWrapper out = VoidFuncWrapper()
out.func = f
return out
Then you can simply do:
cdef dict foobar = {'foo': VoidFuncWrapper.make_from_ptr(foo)}
回答2:
Your problem here is that void*
has no defined converter from a Python object, so a Python wrapper function (that accepts Python objects, converts them, and passes them to the underlying C function) can't be defined, either explicitly with cpdef
or implicitly by putting the cdef
function in a Python object (the dict
in this case).
You could make this work by defining the argument to be something Cython knows how to convert to, e.g.:
cpdef void foo(const char * bar):
pass
cdef dict foobar = {'foo': foo}
Try it online!
But that may not work for your scenario if the function needs to accept an arbitrary pointer. If that's the case, you may want to switch to using C++ containers that can hold your function pointer type directly:
from libcpp.unordered_map cimport unordered_map
from libcpp.string cimport string
cdef void foo(void *bar):
pass
ctypedef void (*f_type)(void *)
cdef unordered_map[string, f_type] foobar
foobar['foo'.encode('ascii')] = foo
来源:https://stackoverflow.com/questions/57461648/cython-throws-an-error-when-pass-function-with-void-argument-to-dict