How to evaluate function handles in mex c++ api

3 次查看(过去 30 天)
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