I completely forgot to follow up on this and it's now several months after the fact. But here's what I ended up doing. It's not the most elegant or efficient solution (I'm sure someone better at MATLAB could make it better), but it works.
The key piece of info I was missing is the fact that the first function in a .m file is the main function and the rest are local functions (many thanks to @Fangjun Jiang for that knowledge). Given that fact, I created a separate .m file containing all of my functions. Then, at the top of the file, I made a selector function to be able to call any of the subsequent functions.
Here's some code, generalized so that people don't get confused by variable names. Suppose that you have functions func_1(a, b, c), func_2(a, b), func_3(a, b, c), and func_4(a, b, c, d) (i.e. all functions have different numbers of arguments), and you don't want to make four separate .m files. Then, you could do this:
% function_selector.m
output = selector(function_name, args)
% function_name should be a string, args should be a cell array
if strcmp(function_name, 'func_1')
[a, b, c] = args{:};
output = func_1(a, b, c);
end
elseif strcmp(function_name, 'func_2')
[a, b] = args{:};
output = func_2(a, b);
end
elseif strcmp(function_name, 'func_3')
[a, b, c] = args{:};
output = func_3(a, b, c);
end
elseif strcmp(function_name, 'func_4')
[a, b, c, d] = args{:};
output = func_4(a, b, c, d);
end
else
assert(false, ["selector() received unknown function name '", function_name, "'"])
end
end
out_1 = func_1(a, b, c)
% Body of func_1
end
out_2 = func_2(a, b)
% Body of func_2
end
out_3 = func_3(a, b, c)
% Body of func_3
end
out_4 = func_4(a, b, c, d)
% Body of func_4
end
Then, wherever you want to use any of the functions in Simulink, you can use a MATLAB Function block. Just include the line
coder.extrinsic("function_selector") % or whatever you named your .m file
at the top of the block (but inside the function). Then, in that block, you can call any of your functions wherever you want to, but with slightly different syntax than normal. Instead of writing
output = func_3(x, y, z);
you would write
output = selector('func_3', {x, y, z});
Note that this solution does require you to write out a pretty extensive if/else tree if you have a lot of functions. Like I said, it's not very elegant. Perhaps if you have a lot of functions and you can number them in an obvious way, you could put them all in an array and then instead of passing the function name as a string into selector(), you could just pass the index of the desired function and then index into the array.