This might be a stupid question, but how can I pass a "raw" pointer to a constructor of a Cython object? The problem appears to be that __init__
and __cinit__
cannot be cdef
or cpdef
but must be def
.
What is the best practice workaround here? Create a wrapper class for the allocated memory?
The following works
# ex1.pyx
from libc.stdlib cimport malloc, free
cdef class Klass1:
cdef void * ptr
cdef void _init(self, void * ptr):
self.ptr = ptr
def bar(self):
free(self.ptr)
def foo():
o = Klass1()
o._init(malloc(100))
o.bar()
While the following does not:
# ex2.pyx
from libc.stdlib cimport malloc, free
cdef class Klass2:
cdef void * ptr
def __init__(self, ptr): # __init__ cannot be cdef
self.ptr = ptr
def bar(self):
free(self.ptr)
def foo():
o = Klass2(malloc(100))
o.bar()
The following setup.py
can be used for building:
from distutils.core import setup
from Cython.Build import cythonize
setup(name='ex1', ext_modules=cythonize('ex1.pyx')) # or ex2.pyx
There's a number of options, depending on the use-case. __init__
/ __cinit__
are designed to construct your classes from Python (where pointers are meaningless) hence the restriction.
In your example (which I suspect is simplified) you could just put the malloc
call inside the constructor:
# rest of class definition goes here
def __init__(self,size):
self.ptr = malloc(size)
# and more code follows
Another possibility would be to use a static method instead of __init__
. (This is actually suggested in the Cython documentation for this purpose: http://docs.cython.org/src/userguide/extension_types.html#c-methods ). I've just copied the example from the documentation:
cdef class OwnedPointer:
cdef void* ptr
cdef __dealloc__(self):
if ptr != NULL:
free(ptr)
@staticmethod
cdef create(void* ptr):
p = OwnedPointer()
p.ptr = ptr
return ptr
A third option is to use wrapper classes as you suggest - the issue with this is that you still have to construct them somehow (and thus you're back to the two techniques mentioned). This would probably be most appropriate where the pointer is actually to a known C/C++ datatype, which you are able to get from another function or construct easily yourself, and it would be useful to be able the handle these from pure Python code. A good outline is at http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#create-cython-wrapper-class - depending on what you wanted to do you might only chose to create a constructor and destructor and not to map the member functions (if there are any).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.