6

是否可以围绕与原始函数具有完全相同名称的函数创建包装器?

这在用户希望在将输入变量传递给内置函数之前对输入变量进行一些额外检查的情况下非常有用如何在 MATLAB IDE 挂起显示非常大的数组时中断它?

4

3 回答 3

11

实际上,除了 slayton 的答案,您不需要使用openvar. 如果您定义一个与 matlab 函数同名的函数,它将隐藏该函数(即被调用)。

为了避免递归调用您自己的函数,您可以使用builtin.

例如

outputs = builtin(funcname, inputs..);

rand.m简单的例子,在matlab路径中命名为:

function out = main(varargin)
disp('Test wrapping rand... calling rand now...');
out = builtin('rand', varargin{:});

请注意,这仅适用于由 找到的函数builtin。对于那些不是,slayton 的方法可能是必要的。

于 2012-08-02T16:35:01.407 回答
3

是的,这是可能的,但它需要一些黑客攻击。它要求您复制一些函数句柄。

使用问题中提供的示例,我将展示如何将函数包装openvar在用户定义的函数中,该函数检查输入变量的大小,然后允许用户取消对太大变量的任何打开操作。

此外,当用户双击 Matlab IDE 的工作区窗格中的变量时,这应该可以工作。

我们需要做三件事。

  1. 获取原始openvar函数的句柄
  2. 定义调用的包装函数openvar
  3. 将原始openvar名称重定向到我们的新函数。

示例函数

function openVarWrapper(x, vector)

    maxVarSize = 10000;
    %declare the global variable
    persistent openVarHandle; 

    %if the variable is empty then make the link to the original openvar
    if isempty(openVarHandle)
        openVarHandle = @openvar;
    end

    %no variable name passed, call was to setup connection
    if narargin==0
        return;
    end


    %get a copy of the original variable to check its size
    tmpVar = evalin('base', x);        

    %if the variable is big and the user doesn't click yes then return
    if prod( size( tmpVar)) > maxVarSize
        resp = questdlg(sprintf('Variable %s is very large, open anyway?', x));
        if ~strcmp(resp, 'Yes')
            return;
        end
    end

    if ischar(x) && ~isempty(openVarHandle);
        openVarHandle(x);
     end
 end

一旦定义了这个函数,那么你只需要执行一个脚本

  • 清除任何命名的变量openvar
  • 运行openVarWrapper脚本来设置连接
  • 将原件openVar指向openVarWrapper

示例脚本:

clear openvar;
openVarWrapper;
openvar = @openVarWrapper;

最后,当你想清理所有东西时,你可以简单地调用:

clear openvar;
于 2012-08-02T16:27:11.677 回答
1

我更喜欢 jmetz 的方法builtin(),因为它可以应用,因为它很干净而且切中要害。不幸的是,很多很多功能都没有找到builtin()

我发现我能够使用which -allcd命令的组合来包装一个函数。我怀疑这种方法可以适用于各种各样的应用程序。

在我的示例案例中,我想(暂时)包装interp1函数,以便我可以检查 NaN 输出值。(interp1默认情况下,该函数将在某些条件下返回 NaN,例如,如果查询点大于最大样本点。)这是我想出的:

function Vq = interp1(varargin)

   persistent interp1_builtin;

   if (isempty(interp1_builtin)) % first call: handle not set
      toolbox = 'polyfun';

      % get a list of all known instances of the function, and then 
      % select the first such instance that contains the toolbox name
      % in its path

      which_list = which('interp1','-all');
      for ii = 1:length(which_list)
         if (strfind(which_list{ii}, [filesep, toolbox, filesep]))
            base_path = fileparts(which_list{ii}); % path to the original function
            current_path = pwd;
            cd(base_path); % go to the original function's directory
            interp1_builtin = @interp1; % create a function handle to the original function
            cd(current_path); % go back to the working directory
            break
         end
      end
   end

   Vq = interp1_builtin(varargin{:});  % call the original function

   % test if the output was NaN, and print a message
   if (any(isnan(Vq)))
      dbstack;
      disp('ERROR: interp1 returned a NaN');
      keyboard
   end

end

另请参阅:如何使用与用户定义函数同名的 MATLAB 工具箱函数

于 2018-05-12T00:18:16.247 回答