【问题标题】:How do i export a function named 'import' from a module in Perl?如何从 Perl 的模块中导出名为“import”的函数?
【发布时间】:2011-03-21 06:34:13
【问题描述】:

我编写了一个特殊的导入函数,将在几个地方使用,我希望能够“使用 ImportRenamer;”在这些模块中并让他们使用从 ImportRenamer 获得的导入。我该怎么办?

编辑:换句话说:我如何在不运行的情况下导入“import”?

【问题讨论】:

  • 问题标题似乎与您真正想做的不符。您是要导出“导入”子程序,还是只想在某些情况下自动运行“导入”? DVK 的回答回答了第二种情况。
  • 这是第一种情况,与我在那里写的完全一样,只是用函数而不是子。我有点困惑,这是怎么不清楚的。 :D
  • @mithaldu - 好的,只是为了确认 - 你想在模块“ImportRenamer”中有一个名为“import”的子,并且(1)当你在“使用 ImportRenamer”时不要运行它名为“MyModule1”的模块; (2) 当您执行use MyModule 时,它将运行ImportRenamer::import() 而不是MyModule::import()?
  • @mithaldu:也许您可以退后一步,解释一下您希望实现的目标,因为您可能为此选择了错误的实现。
  • @mithaldu - 在答案中查看我的更新。我支持 Ether 从上次评论中提出的建议

标签: perl


【解决方案1】:

更新

既然 OP 阐明了他的需求,这确实应该以类似于 Exported 所做的方式来完成,确切地说,通过 glob 分配将子引用注入调用者的命名空间。示例:

###############################################

package ImportRenamer; 
use strict;
sub import_me {
   print "I am a cool importer\n";
}

sub import { 
  my ($callpkg)=caller(0);
  print "Setting ${callpkg}::import to ImportRenamer::import_me\n"; 
  no strict "refs";
  *{$callpkg."::import"} = \&ImportRenamer::import_me; # Work happens here!!!
  use strict "refs";
}
1;

###############################################

package My; 
use strict;
use ImportRenamer; 
1;

###############################################

package My2; 
use strict;
use ImportRenamer; 
1;

###############################################

还有测试:

> perl -e '{  package main; use My; use My2; 1;}'
Setting My::import to ImportRenamer::import_me
I am a cool importer
Setting My2::import to ImportRenamer::import_me
I am a cool importer

原始答案

除了调用导入方法“import”之外,您不需要做任何特别的事情。 use 已经调用了import(),见perldoc use

use Module LIST 

将一些语义从命名模块导入到当前包中, 通常通过将某些子例程或变量名称别名到您的包中。

完全等价于:

 BEGIN { require Module; Module->import( LIST ); }

【讨论】:

  • 我认为这不能回答 OP 的问题。在我看来,他的问题更多,“如何在我的模块中隐藏内置 import?”
  • 正如 JSBangs 所说。您的回答告诉我如何 run 从外部导入。我想导入'import'。
  • @mithaldu - 好的,只是为了确认 - 你想在模块“ImportRenamer”中有一个名为“import”的子,并且(1)当你在“使用 ImportRenamer”时不要运行它名为“MyModule1”的模块; (2) 当您执行use MyModule 时,它将运行ImportRenamer::import() 而不是MyModule::import()?
  • 正确。我并不是特别挑剔 ImportRenamer 中的“import”是什么,但我希望能够“使用 ImportRenamer;”在 MyModule 中,所以 MyModule::import 成为 ImportRenamer 导出的函数。也许我应该看看 Exporter 是如何做到的。
  • @JSBangs - 好的,现在我接受它。更新
【解决方案2】:

您需要在您的模块中编写一个自定义的import 方法,该方法将导出您想要在调用命名空间中调用的函数。

这是一些未经测试的代码:

package ImportMe;

sub import { 

    # Get package name
    my $caller = caller;

    # Install my_import into the calling package as import
    {    no strict 'refs';
         *{"${caller}::import"} = \&my_import;
    }

    return 1;
}

# renamed as import when installing
sub my_import {

   # do stuff

}

现在您可以将use ImportMe; 放入所有模块中,并且将安装import 方法。

【讨论】:

    【解决方案3】:

    作为替代方案,您可以使用 Sub::Exporter 避免在符号表中乱七八糟

    package Your::Module;
    
    use Sub::Exporter (
        -setup => {
            exports => {
                import => sub { return \&_real_import }
            },
            # the "default" group auto-exports "import" without the caller 
            # specifically asking for it
            groups => { default => [qw(import)] },
        }
    );
    
    sub _real_import { ... }
    

    编辑:为自动导出添加了“默认”组

    【讨论】:

      【解决方案4】:

      这样的事情怎么样:

      package Your::Module;
      
      use strict;
      use warnings;
      
      sub import { 
          # gets called by use Your::Module
          my ( $pkg ) = caller;
      
          no strict 'refs';
          *{ $pkg . '::import' } = \&_real_import;
      }
      
      sub _real_import { 
          # import function to be exported to caller
          print "blah blah";
      }
      

      这会手动将_real_import sub 分配给调用包命名空间的import 槽。如果您在 BEGIN 块中执行此操作,那么当 那个 包获得 used 时,import 子应该准备就绪并等待。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-12
        • 1970-01-01
        • 1970-01-01
        • 2018-08-28
        • 1970-01-01
        相关资源
        最近更新 更多