Commit 7acce3e8 authored by Patrik Huber's avatar Patrik Huber

Working prototype of Eigen <=> Matlab conversion

parent 19c69c5e
...@@ -19,26 +19,112 @@ ...@@ -19,26 +19,112 @@
*/ */
#include "mexplus.h" #include "mexplus.h"
#include "Eigen/Core"
#include "mex.h" #include "mex.h"
//#include "matrix.h" //#include "matrix.h"
#include <iostream> #include <iostream>
namespace mexplus {
// Define template specialisations for Eigen::MatrixXd:
template<>
mxArray* MxArray::from(const Eigen::MatrixXd& eigen_matrix) {
const int num_rows = static_cast<int>(eigen_matrix.rows());
const int num_cols = static_cast<int>(eigen_matrix.cols());
MxArray out_array(MxArray::Numeric<double>(num_rows, num_cols));
// This might not copy the data but it's evil and probably really dangerous!!!:
//mxSetData(const_cast<mxArray*>(matrix.get()), (void*)value.data());
// This copies the data. But I suppose it makes sense that we copy the data when we go
// from C++ to Matlab, since Matlab can unload the C++ mex module at any time I think.
// Loop is column-wise
for (int c = 0; c < num_cols; ++c) {
for (int r = 0; r < num_rows; ++r) {
out_array.set(r, c, eigen_matrix(r, c));
}
}
return out_array.release();
};
template<>
void MxArray::to(const mxArray* in_array, Eigen::MatrixXd* eigen_matrix)
{
MxArray array(in_array);
if (array.dimensionSize() > 2)
{
mexErrMsgIdAndTxt("eos:matlab", "Given array has > 2 dimensions. Can only create 2-dimensional matrices (and vectors).");
}
if (array.dimensionSize() == 1 || array.dimensionSize() == 0)
{
mexErrMsgIdAndTxt("eos:matlab", "Given array has 0 or 1 dimensions but we expected a 2-dimensional matrix (or row/column vector).");
// Even when given a single value dimensionSize() is 2, with n=m=1. When does this happen?
}
if (!array.isDouble())
{
mexErrMsgIdAndTxt("eos:matlab", "Trying to create a Eigen::MatrixXd in C++, but the given data is not of type double.");
}
// We can be sure now that the array is 2-dimensional (or 0, but then we're screwed anyway)
auto nrows = array.dimensions()[0]; // or use array.rows()
auto ncols = array.dimensions()[1];
// I think I can just use Eigen::Matrix, not a Map - the Matrix c'tor that we call creates a Map anyway?
Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>> eigen_map(array.getData<double>(), nrows, ncols);
// Not sure that's alright - who owns the data? I think as it is now, everything points to the data in the mxArray owned by Matlab, but I'm not 100% sure.
*eigen_matrix = eigen_map;
};
} // namespace mexplus
using namespace mexplus;
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{ {
using std::vector;
// Check for proper number of input and output arguments: // Check for proper number of input and output arguments:
mexPrintf("nlhs: %d, nrhs: %d\n", nlhs, nrhs); mexPrintf("nlhs: %d, nrhs: %d\n", nlhs, nrhs);
if (nrhs != 2) { if (nrhs != 2) {
mexErrMsgIdAndTxt("eos:example:nargin", "example requires two input arguments."); mexErrMsgIdAndTxt("eos:example:nargin", "Example requires two input arguments.");
} }
else if (nlhs >= 1) { else if (nlhs >= 2) { // 'nlhs >= 1' means no output argument apparently?
mexErrMsgIdAndTxt("eos:example:nargout", "example requires no output argument."); mexErrMsgIdAndTxt("eos:example:nargout", "Example requires zero or one output arguments.");
} }
double *vin1, *vin2; InputArguments input(nrhs, prhs, 2);
vin1 = (double*)mxGetPr(prhs[0]); double vin1 = input.get<double>(0);
vin2 = (double*)mxGetPr(prhs[1]); // Matlab stores col-wise in memory - hence the entry of the second row comes first
mexPrintf("%f, %f\n", *vin1, *vin2); auto vin2 = input.get<vector<double>>(1);
/* auto test = input[1];
MxArray mxa(test);
auto ndim = mxa.dimensionSize();
auto nrows = mxa.dimensions()[0];
auto ncols = mxa.dimensions()[1];
Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>> em(vin2.data(), 2, 3);
// ==> Yes, now I can put exactly this in the MxArray namespace!
std::stringstream ss;
ss << em;
std::string msg = ss.str();
*/
//auto x = MxArray::Numeric<double>(2, 2);
auto asdf = input.get<Eigen::MatrixXd>(1);
std::stringstream ss2;
ss2 << asdf;
std::string msg2 = ss2.str();
OutputArguments output(nlhs, plhs, 1);
output.set(0, asdf);
//double *vin1, *vin2;
//vin1 = (double*)mxGetPr(prhs[0]);
//vin2 = (double*)mxGetPr(prhs[1]);
mexPrintf("%f, %f\n", vin1, vin2[0]);
}; };
void func() void func()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment