假设我试图包裹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
和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
当我运行test.py
时,它会因以下追溯而崩溃:
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'
如果我将module/__init__.pyx
移至module.pyx
和module/__init__.pxd
移至module.pxd
,则相同的代码有效。我错过了什么,我该如何解决?
其他一些相关问题。
MyVector[uint16_t]
而不需要编写另一个包装器?pyxbld
文件?这是多余的吗? (我喜欢pyximport
的便利性,我不想每次手动重新编译代码,而我仍然试图让它工作。)module
编译为独立扩展程序? setup.py
应该是什么样的?deref
。 Cython如何理解我的意思->
以及我的意思.
?我很感激您对这些问题的帮助。
UPD:实际上,我正在包装Google的sparsehash
,我已经找到了way to do what I wanted,但它看起来像是黑魔法。我仍然希望澄清这个错误发生了什么,以及如何正确编写Cython包装器。
答案 0 :(得分:2)
您的主要问题是the code in __init__.so
(generated from __init__.pyx
) does not get executed unless you also have __init__.py
(which does not get executed in this case)。因此,您可以通过创建一个空的__init__.py
文件来解决问题。这一切都像一个凌乱的边缘情况。在原始代码中,MyVector
类永远不会添加到模块中,因此无法通过您描述的错误找到它。
您对其他问题的简短回答是:
不 - 遗憾的是,没有好的方法来构建模板化的包装类。您不需要为只在Cython中使用的任何东西构建包装类。
和
我认为这些最终会成为非常重要的答案,所以我正在跳过它们。 setup.py
似乎比pyximport
更受欢迎,文档中提供了如何使用它的好例子。
Cython在内部跟踪对象的类型。只要它知道它使用指针而->
,就可以用.
代替@Api(
name="myApiName", version = "v1",
namespace = @ApiNamespace(ownerDomain = "test.com", ownerName = "test.com", packagePath = ""),
scopes = {Constants.EMAIL_SCOPE, Constants.PLUS_SCOPE},
clientIds = {Constants.WEB_CLIENT_ID, Constants.ANDROID_CLIENT_ID, Constants.IOS_CLIENT_ID},
audiences = {Constants.ANDROID_AUDIENCE}
)
,这是相当简单的,因为你说你不必自己这样做。
答案 1 :(得分:-1)
你应该考虑使用'swig'。该工具将创建C ++和Python之间交互所需的所有代码。 Link to swig website
我在一个复杂的项目中使用了swig,它运行得非常好。
无论如何,如果您不想在代码中使用此框架,则可以使用swig创建的代码作为参考。