How to evaluate function handles in mex c++ api

9 views (last 30 days)
There is a bit of documentation how to call matlab function from your mex and it works just fine until you try to call something that you didn't know at compile time. Traditionally I would pass a function handle and evalute it from within my mex file, e.g. a solver interface or something like that. The only way I can do this in the c++ api seems to be passing the name of the function instead and calling it via its name. That can't be right? What am I missing here?
Best,
Manuel
  2 Comments
Manuel Schaich
Manuel Schaich on 22 Dec 2018
A possible workaround would be the following:
class MexFunction : public matlab::mex::Function
{
private:
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr;
ArrayFactory factory;
std::ostringstream stream;
void displayError(std::string errorMessage)
{
matlabPtr->feval(matlab::engine::convertUTF8StringToUTF16String("error"),
0, std::vector<Array>({
factory.createScalar(errorMessage) }));
}
void println(void)
{
stream << std::endl;
matlabPtr->feval( u"fprintf",
0,
std::vector<Array>(
{
factory.createScalar(stream.str())
}
)
);
stream.str("");
}
std::string getSignatureFromHandle(Array handle){
if (handle.getType() != ArrayType::HANDLE_OBJECT_REF)
displayError("Non function-handle passed");
std::vector<Array> out = matlabPtr->feval(u"func2str",1,std::vector<Array>({handle}));
if (out.size()!=1)
displayError("Not enough return values from func2str");
if (out[0].getType() != ArrayType::CHAR)
displayError("Problem calling func2str");
size_t i;
char fNameBuffer[255];
TypedArray<char16_t> fName(std::move(out[0]));
for (i=0;i<fName.getNumberOfElements();i++)
fNameBuffer[i] = fName[i];
fNameBuffer[fName.getNumberOfElements()] = '\0';
return std::string(fNameBuffer);
}
public:
MexFunction() : matlabPtr(getEngine()) {}
~MexFunction() {}
void operator()(ArgumentList outputs, ArgumentList inputs){
if (inputs.size() <1)
displayError("Need one input");
std::string funcName = getSignatureFromHandle(inputs[0]);
if (inputs.size()==2){
std::vector<Array> retVal = matlabPtr->feval(funcName, 1, std::vector<Array>({inputs[1]}));
outputs[0] = retVal[0];
}
}
};
Is there a more straight-forward solution?
Manuel Schaich
Manuel Schaich on 23 Dec 2018
The func2str approach does not work when I have specified an inline function definition, i.e. when I do
>> foo = @(x,y)x+y
then func2str returns
>> func2str(foo)
ans =
'@(x,y)x+y'
and this is not callable from feval:
>> feval(func2str(foo),3,4)
Error using feval
Invalid function name '@(x,y)x+y'.
There has to be a way of passing a handle to feval!

Sign in to comment.

Accepted Answer

Harry Vancao
Harry Vancao on 27 Dec 2018
It would appear that this is a limitation of the C++ API for "feval". Although feval in base MATLAB would be able to evaluate a function handle, it does not appear to be possible using the C++ Mex API.
As a workaround, please consider using "eval" instead of feval and then using the "getVariable" method in order to retrieve the results of the evalutated function handle. "eval" should be able to call a function handle in the selected workspace by its name.
  1 Comment
Philip Borghesani
Philip Borghesani on 27 Dec 2018
Edited: Philip Borghesani on 27 Dec 2018
I suggest instead of using eval use a second call to feval that calls MATLAB's feval on the input function pointer:
std::vector<Array> retVal = matlabPtr->feval(u"feval", nlhs, inputs);
Where inputs[0] is the function handle.

Sign in to comment.

More Answers (1)

Manuel Schaich
Manuel Schaich on 2 Jan 2019
Do you expect that this will be added to the feval c++ api? It seems like the most straight forward way of using feval.

Products

Community Treasure Hunt

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

Start Hunting!