How to evaluate function handles in mex c++ api

3 visualizaciones (últimos 30 días)
Manuel Schaich
Manuel Schaich el 22 de Dic. de 2018
Respondida: Manuel Schaich el 2 de En. de 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 comentarios
Manuel Schaich
Manuel Schaich el 22 de Dic. de 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 el 23 de Dic. de 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!

Iniciar sesión para comentar.

Respuesta aceptada

Harry Vancao
Harry Vancao el 27 de Dic. de 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 comentario
Philip Borghesani
Philip Borghesani el 27 de Dic. de 2018
Editada: Philip Borghesani el 27 de Dic. de 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.

Iniciar sesión para comentar.

Más respuestas (1)

Manuel Schaich
Manuel Schaich el 2 de En. de 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.

Productos

Community Treasure Hunt

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

Start Hunting!

Translated by