2013-01-15 16 views
1

我試圖使用一組從林肯·斯坦的網絡編程用Perl IO模塊和正在運行到以下錯誤:Perl模塊,沒有找到IO ::把手型>()阻塞

Can't locate object method "blocking" via package "IO::LineBufferedSessionData" 
at /mxhome/charrison/private/perl/IO/SessionData.pm line 22. 

我從本書的Addison/Wesley網站下載的模塊集合中沒有包含阻塞()子例程,並且經過一番挖掘,我發現它希望調用一個在IO ::中的blocking()子例程的證據Socket或IO :: File,或者IO :: Handle ....實際上在IO :: Handle中有一個blocking()方法。

這裏是IO :: SessionData模塊的頂部,包括它的barfing就行了:

package IO::SessionData; 
# file: IO/SessionData.pm                         
# Figure 13.5: The IO::SessionData Module Code                    

use strict; 
use Carp; 
use IO::SessionSet; 
use Errno 'EWOULDBLOCK'; 
use vars '$VERSION'; 
$VERSION = 1.00; 

use constant BUFSIZE => 3000; 

# Class method: new()                          
# Create a new IO::SessionData object. Intended to be called from within             
# IO::SessionSet, not directly.                        
sub new { 
    my $pack = shift; 
    my ($sset,$handle,$writeonly) = @_; 
    # make the handle nonblocking   
    #######################################################################                      
    $handle->blocking(0);  # <=== THIS IS THE CALL IT FAILS ON 
    ####################################################################### 
    my $self = bless { 
       outbuffer => '', 
       sset  => $sset, 
       handle  => $handle, 
       write_limit => BUFSIZE, 
       writeonly => $writeonly, 
       choker  => undef, 
       choked  => undef, 
       },$pack; 
    $self->readable(1) unless $writeonly; 
    return $self; 
} 

我不知道這是否是足夠的信息來解決問題。我對模塊或面向對象的Perl瞭解甚少。我猜測作者打算在某個超類中調用blocking方法(例如IO :: Handle?)。這本書是在2001年寫的,也許有些規則已經改變了。或者,也許文本有一個錯誤。任何人都可以提出解決方案,或請求更多信息?

更新1:下面是confess生成的堆棧跟蹤只是違規阻塞()調用之前:

/Users/chap/private/wdi/server$ ./server_template -v 
at /Users/chap/private/wdi/lib/IO/SessionData.pm line 21. 
    IO::SessionData::new('IO::LineBufferedSessionData', 'IO::LineBufferedSet=HASH(0x7fcbe19bd450)', 'IO::Socket::INET=GLOB(0x7fcbe18a8070)', undef) called at /Users/chap/private/wdi/lib/IO/LineBufferedSessionData.pm line 21 
    IO::LineBufferedSessionData::new('IO::LineBufferedSessionData', 'IO::LineBufferedSet=HASH(0x7fcbe19bd450)', 'IO::Socket::INET=GLOB(0x7fcbe18a8070)', undef) called at /Users/chap/private/wdi/lib/IO/SessionSet.pm line 46 
    IO::SessionSet::add('IO::LineBufferedSet=HASH(0x7fcbe19bd450)', 'IO::Socket::INET=GLOB(0x7fcbe18a8070)') called at /Users/chap/private/wdi/lib/IO/SessionSet.pm line 136 
    IO::SessionSet::wait('IO::LineBufferedSet=HASH(0x7fcbe19bd450)') called at /Users/chap/private/wdi/lib/IO/LineBufferedSet.pm line 24 
    IO::LineBufferedSet::wait('IO::LineBufferedSet=HASH(0x7fcbe19bd450)') called at ./server_template line 221 

正如你可以看到,新的()被內部調用。 (我的應用程序位於堆棧的底部;其他所有內容均來自本書。)

+0

這個函數是如何調用的? –

+0

調用'new'方法在哪裏?文檔說它不應該直接調用。你可以通過'confess'(會死)或'cluck'(你必須像使用鯉魚qw(cluck)一樣導入)來獲得一個調用堆棧跟蹤。 – amon

+0

查看原始問題的更新1。 – Chap

回答

1

發生了什麼是該類需要傳遞給它的參數(第二個參數),該參數具有->blocking()方法。它應該被調用是這樣的:

my $sset = ...; 
my $handle = IO::Handle->new(...); # build your IO handle 
my $writeonly = ... ; 

my $session_data = IO::SessionData->new($sset, $handle, $writeonly); 

第一線,

my $pack = shift; 

是類名。造成這種情況的慣用名應該是代替:

my $class = shift; 

new經由對象調用語法(該Object::Name->method語法)稱爲通過移動這個額外的變量被自動添加的,它消除該類名從@_,參數名單。其餘的值是構造函數的參數。由於第二個參數被稱爲$handle並且調用該方法,因此您需要將它傳遞給具有該方法的變量。處理該方法的任何東西都會執行,但您可能需要某種IO :: Handle。 :)

響應更新1:

如果你看的痕跡,你會看到:

IO::SessionData::new('IO::LineBufferedSessionData', 'IO::LineBufferedSet=HASH(0x7fcbe19bd450)', 'IO::Socket::INET=GLOB(0x7fcbe18a8070)', undef) 

爲調用方法的東西。 IO::Socket::INETIO::Socket這是一個IO::Handle,所以它應該能夠有->blocking()方法可用。什麼是第21行?

+0

正確 - 儘管如評論所述,這是一種內部調用的方法,而不是我應該直接調用的方法。我假設,不管怎樣,通過繼承的魔力和什麼不是,$ handle可能是某種從IO :: Handle派生的對象,它的blocking()方法應該已被調用。有沒有一種方法來重寫調用來顯式調用IO :: Handle-> blocking(),還是那個不是什麼? – Chap

+0

正確;你不想這樣做。在這種情況下,這就像調用類本身的靜態方法,而不是你想要的! :)該屬性是每個實例的屬性。 –

+0

好吧,事實證明,這是我的一個用戶錯誤。我沒有精確地跟隨這個例子,結果就是這個看似無關的錯誤。如果這些聲稱是生產準備好的,我可能會對他們的使用檢查有一個牛肉,但他們不會......:/ – Chap