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

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

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

Thanks for the suggestion. I tried using that function before and got the following error(s):
Error using mex
/home/PATH/track_cpp_new.cpp: In member function ‘virtual void
MexFunction::operator()(matlab::mex::ArgumentList, matlab::mex::ArgumentList)’:
/home/PATH/track_cpp_new.cpp:514:60: error: no matching function for call to
‘matlab::engine::MATLABEngine::setVariable(const char16_t [9], std::__cxx11::string&)’
matlabPtr->setVariable(u"var_name",variable);
^
In file included from /home/PATH/mexAdapter.hpp:18:0,
from /home/PATH/track_cpp_new.cpp:35:
/home/PATH/cppmex/detail/mexApiAdapterImpl.hpp:313:6: note: candidate: void
matlab::engine::MATLABEngine::setVariable(const u16string&, const matlab::data::Array&, matlab::engine::WorkspaceType)
void matlab::engine::MATLABEngine::setVariable(const std::u16string &varName,
^~~~~~
/home/PATH/cppmex/detail/mexApiAdapterImpl.hpp:313:6: note: no known conversion
for argument 2 from ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ to ‘const matlab::data::Array&’
/home/PATH/cppmex/detail/mexApiAdapterImpl.hpp:327:6: note: candidate: void
matlab::engine::MATLABEngine::setVariable(const string&, const matlab::data::Array&, matlab::engine::WorkspaceType)
void matlab::engine::MATLABEngine::setVariable(const std::string &varName,
^~~~~~
/home/PATH/cppmex/detail/mexApiAdapterImpl.hpp:327:6: note: no known conversion
for argument 1 from ‘const char16_t [9]’ to ‘const string& {aka const std::__cxx11::basic_string<char>&}’
Without the setVariable function, the code compiles without any problems. I'm assuming this is a data type conversion problem, but I am not familiar with the way MATLAB handles its data types.
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
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)

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

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.
"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!