在Cython

时间:2015-04-28 07:53:34

标签: cython eigen eigen3

我正在尝试在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)

感谢。

1 个答案:

答案 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)