0

複数の perl モジュールで同じファイル ハンドルを使用する必要があります。これが私の例です a.pl

#!/usr/bin/perl -w

our $OUT_FILE_HANDLE;

require b;

open($OUT_FILE_HANDLE, ">./a.log");
print $OUT_FILE_HANDLE "text1\n";

b::f($OUT_FILE_HANDLE); // this works

午後

package b;

sub f($) {
  my $a = shift;
  print $a "text2\n";  // get error here
}

f($main::OUT_FILE_HANDLE);
1;

「未定義の値をシンボル参照として使用できません」というエラーが表示されます

b.pm でハンドルを直接 (引数として関数に渡さずに) 使用すると、正常に動作します。

午後

package b;

sub f() {
  print $main::OUT_FILE_HANDLE "text2\n";  // this works
}

f();
1;
4

4 に答える 4

9

あなたの例は、実行の順序が原因で失敗しています.b.pmのすべてがあなたのときに実行されますrequire b;. したがって、開かれる前にファイルハンドルを使用しようとしています。

一般的な原則として、モジュールは呼び出すことができる関数を介してのみ処理を行う必要があります。モジュールが必要な場合は、初期化のみを実行する必要があります。

この場合、最適な設計は、レキシカルファイル ハンドルを使用し、それを必要とする関数に渡すことです。グローバルを使用しないでください。

open(my $OUT_FILE_HANDLE, '>', './a.log') or die "Ouch: $!";
print $OUT_FILE_HANDLE "text1\n";

b::f($OUT_FILE_HANDLE);

グローバルを使用してモジュールと通信することは、ほとんど良い考えではありません。モジュールがグローバルを呼び出し元のコードに公開すると便利な場合もありますが、その逆は決して良い設計ではありません。モジュールが機能するために、特定のパッケージ内に存在する特定の変数に依存するべきではありません。

最後に、Perl でサブルーチン プロトタイプを使用することはほとんどありません。Perl プロトタイプのすべてを知っていて、それを使用する十分な理由がない限り、プロトタイプは省略してください。

sub f {
于 2013-03-28T13:03:44.557 に答える
3

コードには多くの問題があります。

  • 常に use strict、プログラムの先頭またはステートメントuse warningsの直後package

  • CamelCaseパッケージ名とsnake_caseローカル識別子に使用します。Perl に精通している方々に感謝いたします。

  • すべての識別子にわかりやすいものを使用してください。特に、(Perl Compiler Backend) というコア パッケージがあるBため、これでは機能しません。

  • 補助モジュールがmainパッケージからデータにアクセスすることを決して期待しないでください。流れは厳密に下から上にある必要があります

  • サブルーチンにプロトタイプを使用しないでください。この点で Perl は他の言語とは異なり、プロトタイプはいくつかの非常に特別なことを行います。それらが何であるかわからない場合は、プロトタイプを使用するべきではありません。

  • requireそれが何をするのか分からない限り、使用しないでください。あなたはほぼ確実に欲しいuse

  • の 3 パラメーター形式を使用し、それが成功したかどうかopen常に確認します。失敗した場合は、失敗した理由を示す文字列を含めるopen必要がありますdie$!

コードが期待どおりに機能しない主な理由は、require(and ) ステートメントが含まれているときにuse、セカンダリ モジュールで実行可能なステートメントを実行することです。通常、このようなモジュールには、呼び出しコードで使用する定義宣言のみが含まれます。実行可能コードを含める場合は、依存関係が利用できないという問題が発生する可能性があるため、非常に注意する必要があります。

ここにあなたのコードの作業バージョンがあります

main.pl

use strict;
use warnings;

use BB;

open my $fh, '>', 'a.log' or die $!;
print $fh "text1\n";

BB::f($fh);

BB.pm

package BB;

use strict;
use warnings;

sub f {
  my ($a) = @_;
  print $a "text2\n";
}

1;

出力(へa.log)

text1
text2
于 2013-03-28T14:42:02.190 に答える
1

B はPerl コア モジュールであるため、モジュールの名前としては不適切です。名前を BB に変更します (たとえば)。また、Perl のコメントでは「#」も「//」も使用しません。これは私の変更されたコードです(正常に動作します):

main.pl

use BB;

our $OUT_FILE_HANDLE;
open($OUT_FILE_HANDLE, ">", "./a.log") or die $!;
print $OUT_FILE_HANDLE "text1\n";
BB::f($OUT_FILE_HANDLE);

BB.pm

package BB;

sub f {
  my $a = shift;
  print $a "text2\n";  
}
1;
于 2013-03-28T13:25:05.873 に答える
-1

たぶん、「私たちの $OUT_FILE_HANDLE;」を移動します。b.pm パッケージ内。

于 2013-03-28T13:04:14.730 に答える