W przypadku łączenia modułów numerycznych napisanych w różnych językach, dobrą praktyką jest utrzymanie możliwie płaskiej wymiany danych.
najbardziej płaską przedstawieniem libeigen rzeczywistym macierzy jest macierz prądu przemiennego typu rzeczywistego (float lub podwójne)
oto C++ ¹ próbki
#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);
}
Poniżej 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])
być używany jak
python2.7 setup_eigen_python.py install --user
i tutaj jest trochę kierowca testowy
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)
¹Especially, ale zdecydowanie nie ograniczone do, ponieważ konieczności uzyskania bez wspomagania wolałby korzystać z funkcji standardowego języka C++ 2011 e auto
i std::unique_ptr
, ale nie wiedziałem, czy QO ma wystarczające poparcie dla tego.
Możesz użyć [SWIG] (http://www.swig.org/) do wygenerowania opakowania C++, aby Python znał interfejs twojej klasy. Niestety nie znam szczegółów tego procesu, ponieważ sam tego nie zrobiłem (wykorzystałem tylko bibliotekę, w której zostało to zrobione), dlatego nie jest to odpowiedź, a komentarz. – wakjah
Czy możesz potwierdzić, że chcesz utworzyć rozszerzenie C++ dla Pythona? Innymi słowy chcesz, aby twoja funkcja C++ Cov() była dostępna dla twojego skryptu Python? Jeśli tak, to w zasadzie chcesz użyć funkcji PyArg_ * do wyodrębnienia danych z argumentów funkcji Pythona do zmiennej C++ (nie do PyObject, jak to zrobiono powyżej), a następnie użyj funkcji PyBuild *, aby przekazać wynik z powrotem do Pythona. Jeśli podasz kod Pythona, który pokazuje przykład użycia, możemy wysłać odpowiedź. – Schollii
Wspomniałeś, że nie możesz użyć wzmocnienia. Ale SWIG to narzędzie, którego użyłem dużo, ponieważ generuje kod C++, który wykonuje wszystkie wywołania PyArg i PyBuild itd., Z wyjątkową propagacją itp. Wszystko, co musisz zrobić, aby użyć SWIG, zainstaluj go na swoim komputerze, stwórz Plik .i, który zawiera .h twojej klasy MatrixXd i funkcję Cov, uruchom ją, zbuduj bibliotekę wygenerowaną przez SWIG i uruchom Pythona: możesz wtedy wywołać swój Cov z Pythona, w ogóle nie będziesz miał C API! – Schollii