在 Cython 中设置 coefficient/element of Eigen::Matrix3d

Set coefficient/element of Eigen::Matrix3d in Cython

我正在尝试在 Cython 中为使用 Eigen::Matrix3d 矩阵的库创建一个包装器。如何设置 Matrix3d 对象的单个 element/coefficient?

我知道,我可以使用 coeff(row, col) 方法获取值,但找不到任何函数 set_coeff(row, col, value) - 或者可能被调用 - 来设置值。

在使用

声明 Matrix3d 之后
cdef decl_eigen.Matrix3d t = decl_eigen.Matrix3d()

我想设置值,但是 none 以下构造在 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)

谢谢。

它并不像它应该的那么简单,但你可以让它发挥作用。

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 中访问它。我假设它 returns a double& - 我实际上无法在 Eigen 中找到定义,因为它深埋在模板 class 层次结构中(它实际上并不重要 returns - 它表现得像 returns double&,应该足够好了)。

不幸的是,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)