Let's say I'm trying to wrap vector.
module/__init__.pxd:
from libcpp.vector cimport vector from libc.stdint cimport uint32_t cdef class MyVector: cdef vector[uint32_t]* thisptr module/__init__.pyx:
from libc.stdint cimport uint32_t from libcpp.vector cimport vector from cython.operator cimport dereference as deref cdef class MyVector: # the field declaration is in *.pxd def __cinit__(self): self.thisptr = new vector[uint32_t]() self.thisptr.push_back(42) def __dealloc__(self): del self.thisptr self.thisptr = <vector[uint32_t]*> NULL def mysize(self): return self.thisptr.size() def myget(self): return deref(self.thisptr)[0] module/__init__.pyxbld and run.pyxbld:
def make_ext(modname, pyxfilename): from distutils.extension import Extension return Extension( name=modname, sources=[pyxfilename], language='c++' ) run.pyx:
from module cimport MyVector cdef main(): obj = MyVector() print(obj.thisptr.size()) # 1 print(obj.mysize()) # 1 print(obj.myget()) # 42 main() test.py:
import pyximport pyximport.install() import run When I run test.py, it crashes with the following traceback:
Traceback (most recent call last): File "/usr/lib64/python3.4/site-packages/pyximport/pyximport.py", line 210, in load_module mod = imp.load_dynamic(name, so_path) File "module/__init__.pxd", line 5, in init run (/home/pastafarianist/.pyxbld/temp.linux-x86_64-3.4/pyrex/run.cpp:918) cdef class MyVector: AttributeError: 'module' object has no attribute 'MyVector' The same code works if I move module/__init__.pyx to module.pyx and module/__init__.pxd to module.pxd. What am I missing and how do I fix it?
A few other related questions.
- Is there any way to expose a templated wrapper to Cython code, so that I can have
MyVector[uint16_t]without needing to write another wrapper? - Am I correct in adding a
pyxbldfile for each source file which interacts with C++ code? Is this redundant? (I like the convenience ofpyximportand I don't want to recompile the code every time manually while I'm still trying to get it to work.) - How do I compile
moduleto a standalone extension? What shouldsetup.pylook like? - In the above code I never used
derefbefore calling C++ methods. How does Cython understand where I mean->and where I mean.?
I would appreciate help with any of these questions.
UPD: actually, I was wrapping Google's sparsehash, and I have figured out a way to do what I wanted, but it looks like black magic. I would still appreciate a clarification of what was going on with this error and how to write Cython wrappers properly.