How do I invoke a shadowed core MATLAB function (not built-in) from an overloaded function of same name

조회 수: 22 (최근 30일)
In an application I wanted to add a calling jacket for MATLAB's print. I was trying to add a print option -dsvg which used the great resource plot2svg.m to print to .svg, while using MATLAB's regular print for all other cases.
If I name my function print() in my local project folder, I can shadow the main print function for this application only, but I cannot then call base MATLAB print inside my custom version of print. I had thought
builtin('print' ...)
would do the trick, but print is not built-in so cannot be accessed in this way. I could use run command which changes directory but that seems "dodgy" (one would want to use try-catch to preserve directory in the case of print failure, at least). I could give my function a different name, but then I have to locate and change every call to "print" in my app, which is exactly what I was seeking to avoid!
Is there an nice way of doing this? Any help gratefully received.

채택된 답변

Julian
Julian 2014년 8월 14일
A colleague gave me this answer, which I have used. I put the following code into the top of my overlay function (print() in my case):
persistent shipped % stores a handle to the shipped MATLAB funtion of the same name
if isempty(shipped)
this = [mfilename '.m']; % the name of function in MATLAB we are shadowing
list = which(this, '-all'); % find all the functions which shadow it
f = strncmp(list, matlabroot, length(matlabroot)); % locate 1st in list under matlabroot
list = list{find(f, 1)}; % extract from list the exact function we want to be able to call
here = cd(list(1:end-length(this))); % temporarily switch to the containing folder
shipped = str2func(this(1:end-2)); % grab a handle to the function
cd(here); % go back to where we came from
end
The first time it is used it locates the base MATLAB function which is shadowed by the function containing the above code, and creates a handle to the base function which is available for all subsequent calls to use as needed.
  댓글 수: 3
Adam Danz
Adam Danz 2020년 9월 28일
편집: Adam Danz 2021년 3월 26일
+1 I've used and recommended this solution several times.
The version below make the following changes:
  • uses fileparts to isolate the path and file name rather than using string indexing
  • replaces length with numel which is more robust but makes no difference in this case.
  • Uses onCleanup to return the cd() in case of errors.
  • If a shadowed core function is not found, instead of resulting in an error, this will store the files' name as the shipped function handle.
Also be aware that the function and file name must match. This, therefore, cannot be used with local or nested functions.
persistent shipped % stores a handle to the shipped MATLAB funtion of the same name
if isempty(shipped)
this = [mfilename '.m']; % the name of function in MATLAB we are shadowing
list = which(this, '-all'); % find all the functions which shadow it
f = strncmp(list, matlabroot, numel(matlabroot)); % locate 1st in list under matlabroot
if any(f)
[funcpath,funcname] = fileparts(list{find(f, 1,'first')}); % extract from list the exact function we want to be able to call
here = cd(funcpath); % temporarily switch to the containing folder
cleanup = onCleanup(@()cd(here)); % go back to where we came from
shipped = str2func(funcname); % grab a handle to the function
clear('cleanup')
else
shipped = str2func(['@',mfilename]);
end
end
user001
user001 2021년 3월 26일
This does not work if the shadowing function is in a private directory, since private functions have higher precedence than the current directory. Is there any solution in that case?

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

추가 답변 (1개)

Christopher Berry
Christopher Berry 2014년 8월 14일
편집: Christopher Berry 2014년 8월 14일
Julian,
I think you had the right idea with the run command to call print, but use the fullpath instead of cd into the directory. You can also use matlabroot to keep your script portable as well:
printMatlab = fullfile(matlabroot,'toolbox','matlab','graphics','print.m');
run(printMatlab)
As long as the script (here just print) does not change the directory it is in, run will return to the correct working directory on success or failure, so you do not need to worry about using try-catch yourself.
  댓글 수: 3
Christopher Berry
Christopher Berry 2014년 8월 14일
You are right, without arguments print is not all that useful. I was looking for a way around this when I saw your post.
Julian
Julian 2014년 8월 14일
A subsidiary question emerges though, how might I reference the help in the base / shipped function? If I put "See also PRINT" in my print overlay, clicking it just echoes the help in my function, rather than produce the help for the shadowed function....

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

카테고리

Help CenterFile Exchange에서 Structures에 대해 자세히 알아보기

제품

Community Treasure Hunt

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

Start Hunting!

Translated by