How to evaluate function handles in mex c++ api

9 Ansichten (letzte 30 Tage)
Manuel Schaich
Manuel Schaich am 22 Dez. 2018
Beantwortet: Manuel Schaich am 2 Jan. 2019
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 Kommentare
Manuel Schaich
Manuel Schaich am 22 Dez. 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 am 23 Dez. 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!

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Harry Vancao
Harry Vancao am 27 Dez. 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 Kommentar
Philip Borghesani
Philip Borghesani am 27 Dez. 2018
Bearbeitet: Philip Borghesani am 27 Dez. 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.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Manuel Schaich
Manuel Schaich am 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.

Produkte

Community Treasure Hunt

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

Start Hunting!

Translated by