How do I pass a string from a C++ Mex file to the MATLAB workspace?

26 views (last 30 days)
I am trying to pass a string from a C++ Mex file I am working on to the MATLAB workspace for plotting purposes. It is a fairly complicated program, but all I want to do is pass a std::string in my MexFunction (which I defined as "var") to the MATLAB workspace. This is the important part of the code:
#include "mex.hpp"
#include "mexAdapter.hpp"
using namespace matlab::data;
using namespace matlab::engine;
using namespace std;
using matlab::mex::ArgumentList;
// "some code here" //
class MexFunction : public matlab::mex::Function{
public:
void operator()(ArgumentList outputs, ArgumentList inputs){
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
ArrayFactory factory;
// "more code here" //
for(int i = 0; i < 100; i++){
std::vector<ToolData> toolData = apiSupportsBX2 ? capi.getTrackingDataBX2() : capi.getTrackingDataBX();
for (int i = 0; i < toolData.size(); i++)
{
std::string var = toolDataToCSV(toolData[i]);
std::cout << var << std::endl;
// Pass "var" to MATLAB here //
}
usleep(5000);
}
matlabPtr->eval(u"printData = true");
// "more code here" //
std::cout << "Press Enter to continue...";
std::cin.ignore();
}
};
I'm fairly new to C++/MATLAB-implementations and don't have that much experience with Mex file programming, so thanks in advance!

Accepted Answer

Guillaume
Guillaume on 7 May 2019
Edited: Guillaume on 7 May 2019
matlab:engine::setvariable seems to be the function to do that. With your original C++ code (not the C interface)
matlabPtr->setVariable(u"variablename", var); //%don't use var as variable name in matlab. It's the variance function.
Untested. I've never used the C++ interface.
  3 Comments
Guillaume
Guillaume on 15 May 2019
I'm assuming this is a data type conversion problem, but I am not familiar with the way MATLAB handles its data types.
I would say it's a purely C++ problem. You try to call a C++ function with arguments that don't match the function signature. In particular, as documented in the link in my answer, the second argument to setVariable has to be of type matlab::data::Array.
You can easily construct that object as demonstrated here:
matlab::data::ArrayFactory factory;
matlabPtr->setVariable(u"variablename", factory.createCharArray(var)); //assuming var is std::string
André C. D.
André C. D. on 15 May 2019
EDIT: I managed to make it work now, I had forgotten to use factory.createCharArray() before setVariable and now it works.
So at the end, I used the original code and added this:
Array str = factory.createCharArray(var); //var is of type std::string
matlabPrt->setVariable(u"StringName",str);
Thank you for the tip!

Sign in to comment.

More Answers (1)

Sreelakshmi S.B
Sreelakshmi S.B on 6 May 2019
You can convert var to an mxArray and use 'engPutVariable' to write the mxArray into the Matlab Engine Worspace.You can find details about using this function in C and Fortran at this link: https://in.mathworks.com/help/matlab/apiref/engputvariable.html
This will work with C++ too.
  2 Comments
André C. D.
André C. D. on 6 May 2019
Edited: André C. D. on 6 May 2019
Hi, thanks for the response. The problem with using engPutVariable, is that whenever I include "engine.h", I get the following error when compiling the Mex file:
#error Using MATLAB Data API with C Matrix API is not supported
I am assuming this is because I have included "mex.hpp" and/or "mexAdapter.hpp". How should I go about solving this problem?
EDIT:
I have replaced the header files "mex.hpp" and "mexAdapter.hpp" with only "engine.h" and used the same method as explained in engdemo.c ('extern/examples/eng_mat/engdemo.c') and now have the following code:
#include "engine.h"
#pragma comment(lib,"libmat.so")
#pragma comment(lib,"libmx.so")
#pragma comment(lib,"libmex.so")
#pragma comment(lib,"libeng.so")
// "Code" //
int main(){
Engine *ep;
mxArray *pointer;
for(int i = 0; i < 100; i++){
std::vector<ToolData> toolData = apiSupportsBX2 ? capi.getTrackingDataBX2() : capi.getTrackingDataBX();
for (int i = 0; i < toolData.size(); i++)
{
std::string var = toolDataToCSV(toolData[i]); //toolDataToCSV returns string
std::cout << var << std::endl;
char ch[var.size() + 1];
strcpy(ch, var.c_str()); //conversion from std::string to char
pointer = mxCreateString(ch);
memcpy((void *)mxGetPr(ch), (void *)ch, sizeof(ch));
engPutVariable(ep, "ch", ch);
}
usleep(10000);
}
mxDestroyArray(pointer);
engEvalString(ep, "close;");
return 0;
}
And now the issues I get are:
cannot convert 'char*' to 'const mxArray* {aka const mxArray_tag*}' for argument '1' to 'double* mxGetPr(const mxArray*)';
cannot convert 'char*' to 'const mxArray* {aka const mxArray_tag*}' for argument '3' to 'int engPutVariable(ep, "ch", ch);
Using mxGetString instead of mxGetPr also leads to a smilar data conversion issue.
Sreelakshmi S.B
Sreelakshmi S.B on 7 May 2019
"The MATLAB Data API supports modern C++ features and is not compatible with the C Matrix API" ------- as taken from the official documentation page.This is why the initial error is happening.
You can try using 'setVariable' instead.This link has more details on how to go about doing that:

Sign in to comment.

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!