1 题: 在python中使用Eigen Library函数调用C ++

在...创建的问题 Thu, Jul 24, 2014 12:00 AM

我在Eigen Library的帮助下用C ++进行一些计算,函数是这样的:

 
MatrixXd Cov(MatrixXd Data)
{

  VectorXd meanVector;
  ...
  return Covariance;
}

..在wrap python函数中:

 
static PyObject *Wrap_Cov(PyObject *self,PyObject *args)
{   
      Pyobject *Objectdata;

      if(!PyArg_ParseTuple(args,"O", &ObjectData))
        return NULL;

      Cov(ObjectData);

      return Py_BuildValue("O",&covariance_answer);

  }

显然,Python不知道我定义的''对象',它不能将''MatrixXd''转换为''对象'',我认为它是某种''数组'',而不是' '对象''

如何在不使用提升的情况下执行此操作?

    
14
  1. 您可以使用 SWIG 生成C ++包装器,以便Python知道您的类的接口。不幸的是我不知道这个过程的细节,因为我自己没有这样做(只使用了已经完成的库),这就是为什么这是一个注释而不是答案。
    2013-03-22 15:20:35Z
  2. 您能否确认要为Python创建C ++扩展?换句话说,您想让您的C ++ Cov()函数可用于您的Python脚本吗?如果是这样,你基本上想要使用PyArg_ *函数将Python函数参数中的数据提取到C ++变量(不像上面那样是PyObject),然后使用PyBuild *函数将结果传递回Python。如果您提供显示示例用例的python代码,那么我们可以发布答案。
    2013-08-13 05:42:03Z
  3. 你提到你不能使用boost。但SWIG是一个我已经使用很多的工具,因为它生成了C ++代码,可以为您执行所有PyArg和PyBuild等调用,具有异常传播等功能。使用SWIG所需要做的就是将它安装在您的计算机上,创建一个.i文件包含你的MatrixXd类和Cov函数的.h,运行它,构建SWIG生成的库,并启动Python:然后你可以从Python调用你的Cov,你根本就没有C API可以使用!
    2013-08-13 05:44:42Z
  4. @ Schollii:哇谢谢!这是一个很好的建议。我将尽力记住我的个人项目。
    2013-09-09 09:49:18Z
  5. 你想要一个Cython或SWIG解决方案,还是想要用纯C编写这个包装?
    2014-05-21 15:11:30Z
  6. 醇>
    1答案                              1 跨度>                         

    如果连接用不同语言编写的数字模块,最好尽量保持数据交换。

    自由实矩阵的最平坦表示是实数类型的c数组(浮点数或双精度)

    这是一个C ++¹样本


     
    #include <stdexcept>
    #include <iostream>
    #include <string>
    #include <sstream>
    #include <python2.7/Python.h>
    #include <eigen3/Eigen/Dense>
    
    
    using std::size_t;
    typedef double real_t;
    
    typedef Eigen::Matrix<real_t, Eigen::Dynamic, Eigen::Dynamic> 
            Matrix;
    
    static PyObject* p_eigen_python_error(NULL);
    
    static PyObject *
    randomDxDMatrix(PyObject *self, PyObject *args) {
        PyObject* p(NULL);
        PyObject* item(NULL);    
    
        try{
            size_t d(0);
    
            PyArg_ParseTuple(args, "L", &d);
            Matrix M = Matrix::Random(d,d);
    
            size_t length = d * d;
    
            p = PyList_New(length);
    
            if (p == NULL) {
                std::stringstream msg;
                msg << "Could not allocate a Pylist of "
                    << d << "x" << d << " = " << d*d 
                    << " size for the return Object";
                throw std::runtime_error(msg.str().c_str());
            } else {
                for (size_t i = 0; i < length; ++i) {
                    item = PyFloat_FromDouble(M.data()[i]);
                    PyList_SET_ITEM(p, i, item);
                }   
            }
    
        } catch (const std::exception& e) {
            delete p; p = NULL;
            delete item; item = NULL;
    
            std::string msg = ("randomDxDMatrix failed: ");
            msg += e.what();
            PyErr_SetString(p_eigen_python_error, msg.c_str());
        }
    
        return p;
    }
    
    static PyMethodDef EigenMethods[] = {
        {"randomDxDMatrix",  randomDxDMatrix, METH_VARARGS, 
        "Gets a random DxD matrix column-major as a list of (python) floats"},
        {NULL, NULL, 0, NULL}        /* Sentinel */
    };
    
    PyMODINIT_FUNC
    initeigen_python(void) {
    
        PyObject* p;
    
        p = Py_InitModule("eigen_python", EigenMethods);
        if (p == NULL)
            return;
    
        p_eigen_python_error = PyErr_NewException(
                                    const_cast<char*>("eigen_python.error"), 
                                    NULL, NULL
                                );
        Py_INCREF(p_eigen_python_error);
        PyModule_AddObject(p, "error", p_eigen_python_error);
    }
    

    这是setup_eigen_python.py


     
    from distutils.core import setup, Extension
    
    cpp_args = ['-Wall', '-pedantic']
    cxx_args = ['-std=c++11'].extend(cpp_args)
    
    module_eigen_python = Extension('eigen_python',
                              define_macros = [('MAJOR_VERSION', '0'),
                                                ('MINOR_VERSION', '1')],
                              include_dirs = ['/usr/local/include'],
                              sources = ['eigen_python.cpp'],
                              extra_compile_args = cpp_args
    #                          sources = ['eigen_python.cxx'],
    #                          extra_compile_args = cxx_args
                          )
    
    setup (name = 'eigen_python',
           version = '0.1',
           description = 'This is just a demo',
           author = 'Solkar',
           url = 'http://stackoverflow.com/questions' 
             + '/15573557/call-c-using-eigen-library-function-in-python',
           long_description = 'just a toy',
           ext_modules = [module_eigen_python])
    

    一样使用  
    python2.7 setup_eigen_python.py install --user
    

    这里有一个小测试驱动程序


     
    import eigen_python as ep
    import numpy as np
    
    DIM = 4
    
    M = np.array(ep.randomDxDMatrix(DIM), order="F")
    M.shape= DIM,DIM
    
    print(M) 
    

    ¹特别是,但到目前为止还没有限制,因为必须在没有提升的情况下相处,会更喜欢使用C ++ 2011标准的功能,如autostd::unique_ptr,但我不知道QO是否有足够的支持。

        
    7
    2014-07-24 17:24:46Z
来源放置 这里