Can anonymous function handles be inputs of functions that are turned into C code using MATLAB Coder (codegen)?

3 views (last 30 days)
I have a function, call it foo(), that accepts a number of arguments as inputs. Say, in this case, the definition of foo()'s inputs look like this:
function [x] = foo(f,lb,ub)
where f is a function_handle, and lb and ub are doubles.
I would like to use the codegen() function in MATLAB R2017a to turn this into a MEX file. When I run coder.screener('foo'), I get the all clear, but I cannot figure out how to actually create the args input in the codegen function. For example:
codegen foo.m -args {{X},0,0}
In this case, {X} should be a function_handle type, but it appears that it is unsupported or not easily accessible. I do get the following error when I run the codegen function:
Function input at args{1} does not have a valid type.
Caused by:
Class function_handle is not supported by coder.Type.
Use help codegen for more information on using this command.
Error using codegen
Can I achieve what I am trying to do (create a MEX file of a function that requires a function_handle as an input argument) or is this still unsupported?

Accepted Answer

Ryan Livingston
Ryan Livingston on 8 Oct 2017
This is not supported. When running the MEX file, Coder typically needs to have generated code for the function handle f may refer to. That means that Coder would need to know all possible values of f. There's no way to specify such a thing for Coder.
A couple of options I see:
1. If f will be a single fixed function for a given MEX file, then just encode that in your MATLAB code. I assume this isn't the case given your question, but just mention it for completeness.
2. Pass f as a character row vector representing the function name. There are 2 possibilities here. First, if you know the possible set of all functions which could be passed then do something like:
function [x] = foo(fname,lb,ub)
% Dispatcher wrapper
switch fname
case 'function1'
x = foo_sub(@function1,lb,ub);
case 'function2'
x = foo_sub(@function2,lb,ub);
end
function [x] = foo_sub(f,lb,ub)
% Original implementation of foo
x = f(lb,ub);
and so on. This lets Coder use specific values for your function handle and is a way to tell it about the possibilities without hard-coding one.
If the possible values of fname aren't known, then we could treat it as an extrinsic function:
function [x] = foo(fname,lb,ub)
x = zeros(...); % pre-assign x to give it the right size, type, complexity
x = feval(fname,lb,ub); % use feval to call fname; fname is extrinsic in MATLAB Coder
This works because feval is always treated as an extrinsic function by Coder in MEX. This means that rather than generating code for feval, the generated MEX file calls back into MATLAB via something like mexCallMATLAB to evaluate feval. That means that you can call whatever objective function you'd like via feval since it is simply being run in MATLAB.
3. You could use a hybrid of the approaches from (2). Suppose you've got a few important objective functions that benefit from code generation. Then use those as the specific cases in your switch and use feval in the otherwise branch. That way you can get potential codegen benefits for the important cases while maintaining broader support.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!