How to evaluate function handles in mex c++ api

조회 수: 5 (최근 30일)
Manuel Schaich
Manuel Schaich 2018년 12월 22일
답변: Manuel Schaich 2019년 1월 2일
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
Manuel Schaich
Manuel Schaich 2018년 12월 22일
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 2018년 12월 23일
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!

댓글을 달려면 로그인하십시오.

채택된 답변

Harry Vancao
Harry Vancao 2018년 12월 27일
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
Philip Borghesani
Philip Borghesani 2018년 12월 27일
편집: Philip Borghesani 2018년 12월 27일
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.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

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

카테고리

Help CenterFile Exchange에서 Write C++ Functions Callable from MATLAB (MEX Files)에 대해 자세히 알아보기

제품

Community Treasure Hunt

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

Start Hunting!

Translated by