我正在尝试在Cython中为使用Eigen :: Matrix3d矩阵的库创建一个包装器。如何设置Matrix3d对象的单个元素/系数?
我知道,我可以使用coeff(row, col)
方法获取值,但找不到任何函数set_coeff(row, col, value)
- 或者可能会调用 - 来设置值。
用
声明Matrix3d后cdef decl_eigen.Matrix3d t = decl_eigen.Matrix3d()
我想设置值,但以下结构中没有一个在Cython中起作用:
t << 1,2,3,4,5,6,7,8,9
t(0,0) = 1
t[0][0] = 1
我不能使用带有值的构造函数,因为根据我的知识,它不存在。
以下是我目前提出的文件:
decl_eigen.pxd :
cdef extern from "Eigen/Dense" namespace "Eigen":
cdef cppclass Vector3d:
Matrix3d() except +
double coeff(int row, int col)
decl_foo.pxd :
cimport decl_eigen
cdef extern from "../foo.hpp" namespace "MyFoo":
cdef cppclass Bar:
Bar() except +
void transform(decl_eigen.Matrix3d &transformation)
foo.pyx :
import decl_eigen
cimport decl_foo
cdef class Bar:
cdef decl_foo.Bar *thisptr
def __cinit__(self):
self.thisptr = new decl_foo.Bar()
def __dealloc__(self):
del self.thisptr
def transform(self, transformation):
cdef decl_eigen.Matrix3d t = decl_eigen.Matrix3d()
for i in range(3):
for j in range(3):
k = i*3 + j
# Set the coefficient of t(i,j) to transformation[k], but how????
self.thisptr.transform(t)
感谢。
答案 0 :(得分:4)
它并不像它应该的那样简单,但你可以使它发挥作用。
Eigen中的元素访问主要通过operator()
完成:
// (copied from http://eigen.tuxfamily.org/dox/GettingStarted.html)
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
因此,我们需要定义operator(),以便您可以在Cython中访问它。我假设它返回一个double&
- 我实际上找不到Eigen中的定义,因为它深深埋藏在模板类层次结构中(它实际上返回的并不是非常重要 - 它的作用就像它返回一个双重&amp; ,这应该足够好了。
不幸的是,operator()
在Cython中似乎有点破碎(参见Cython C++ wrapper operator() overloading error)所以我们必须将其别名为别名。我使用过element
。
cdef extern from "eigen3/Eigen/Dense" namespace "Eigen":
# I'm also unsure if you want a Matrix3d or a Vector3d
# so I assumed matrix
cdef cppclass Matrix3d:
Matrix3d() except +
double& element "operator()"(int row,int col)
原则上我们希望能够m.element(0,0) = 5
。但是,Cython不喜欢这个。因此,我必须通过稍微复杂的指针类型机制分配来创建一个函数。
cdef void set_matrix_element(Matrix3d& m, int row, int col, double elm):
cdef double* d = &(m.element(row,col))
d[0] = elm
因此,要设置矩阵元素,我们只需调用此函数。这是我测试它的功能:
def get_numbers():
cdef Matrix3d m = Matrix3d()
cdef int i
for i in range(3):
set_matrix_element(m,i,i,i)
return m.element(0,0),m.element(1,1),m.element(2,2),m.element(1,2)
# returns 0,1,2, and something else (I get 0, but in principle
# I think it's undefined since it's never been specifically set)