这似乎是一个应该有明显答案的问题,但出于某种原因,我无法在线找到任何示例。
我使用Cython在Python类中包装C ++对象的向量。我还有一个已编码的C ++类的Cython包装器。我可以使用__len__()
,__getitem__()
和resize()
等多种方法正常工作,但__setitem__()
方法给了我一些问题。
为简单起见,我使用int
s的向量编码了一个小例子。我想如果我可以使这个代码工作,那么我可以构建它以获得我的C ++类的解决方案。
MyPyModule.pyx
# distutils: language = c++
from libcpp.vector cimport vector
from cython.operator cimport dereference as deref
cdef class MyArray:
cdef vector[int]* thisptr
def __cinit__(self):
self.thisptr = new vector[int]()
def __dealloc__(self):
del self.thisptr
def __len__(self):
return self.thisptr.size()
def __getitem__(self, size_t key):
return self.thisptr.at(key)
def resize(self, size_t newsize):
self.thisptr.resize(newsize)
def __setitem__(self, size_t key, int value):
# Attempt 1:
# self.thisptr.at(key) = value
# Attempt 2:
# cdef int* itemptr = &(self.thisptr.at(key))
# itemptr[0] = value
# Attempt 3:
# (self.thisptr)[key] = value
# Attempt 4:
self[key] = value
当我尝试使用Attempt 1进行cythonize时,我收到了错误Cannot assign to or delete this
。当我尝试尝试2时,创建了.cpp
文件,但编译器抱怨:
error: cannot convert ‘__Pyx_FakeReference<int>*’ to ‘int*’ in assignment
__pyx_v_itemptr = (&__pyx_t_1);
在尝试3时,Cython不会构建文件,因为Cannot assign type 'int' to 'vector[int]'
。 (当我用C ++对象而不是int
尝试这种风格时,它抱怨因为我有一个引用作为左值。)尝试4编译,但当我尝试使用它时,我得到一个段错误。 / p>
Cython docs表示不支持将引用作为左值返回,这很好 - 但是如何绕过它以便我可以为其中一个向量元素赋值?
答案 0 :(得分:2)
通过指针访问向量有两种方法,
def __setitem__(self, size_t key, int value):
deref(self.thisptr)[key] = value
# or
# self.thisptr[0][key] = value
Cython将这两种情况翻译如下:
Python: deref(self.thisptr)[key] = value
C++: ((*__pyx_v_self->thisptr)[__pyx_v_key]) = __pyx_v_value;
Python: self.thisptr[0][key] = value
C++: ((__pyx_v_self->thisptr[0])[__pyx_v_key]) = __pyx_v_value;
是等效的,即访问相同的矢量对象。
答案 1 :(得分:1)
您可以让Cython自己为您执行此操作,而不是尝试处理来自Cython代码的指针:
cdef class MyArray:
cdef vector[int] thisptr
def __len__(self):
return self.thisptr.size()
def __getitem__(self, size_t key):
return self.thisptr[key]
def __setitem__(self, size_t key, int value):
self.thisptr[key] = value
def resize(self, size_t newsize):
self.thisptr.resize(newsize)
这种方法有问题吗?
答案 2 :(得分:0)
我已经接受了J.J. Hakala的回答(非常感谢!)。我调整了该方法以包含越界检查,因为它使用[]
运算符而不是at()
方法:
cdef class MyArray:
(....)
def __setitem__(self, size_t key, int value):
if key < self.thisptr.size():
deref(self.thisptr)[key] = value
else:
raise IndexError("Index is out of range.")