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
pyxbld
file for each source file which interacts with C++ code? Is this redundant? (I like the convenience ofpyximport
and 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
module
to a standalone extension? What shouldsetup.py
look like? - In the above code I never used
deref
before 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.