2010-07-12 80 views
1

我正在嘗試在Windows中使用Ruby進行一些腳本化的GUI測試。我正在利用pragprog book的指導,並且我遇到了一些問題。我已經分析了一些代碼來幫助重複繪製win32api函數。代碼如下:當沒有參數提供時,Ruby的* args導致seg錯誤

module WindowsGui 

    def self.def_api(function, parameters, return_value)    
    api = Win32API.new 'user32', function, parameters, return_value 

    define_method(function.snake_case) do |*args|     
     api.call *args             
    end 

    end 
end 

...所以,我可以使用塊下面的方式來定義模塊中的多個win32APIs:

def_api 'FindWindow', ['P', 'P'], 'L' 

我有一些RSpec的測試,以確保這表現得應該如此。

it 'wraps a Windows call with a method' do 
    find_window(nil, nil).should_not == 0 
    end 

    it 'enforces the argument count' do 
    lambda {find_window}.should raise_error 
    end 

一切工作正常,第一次測試,第二次導致seg故障。似乎如果我沒有參數調用這個,我不能碰*參數 - 但我可以做一個args.length來看看它是空的。

爲什麼會導致seg故障而不是異常?通過諸如此類的解決方案來解決這個問題是否可以接受......

​​

還有一個問題太長了 - 對不起。

TIA! Bob

回答

1

它是段錯誤的可能原因是因爲Win32API之下的某個地方缺少參數是翻譯成一個或多個NULL指針取消引用。

如果您要創建類似這樣的函數,那麼您應該考慮添加一個per-api-call,布爾返回參數驗證塊(或lambda)作爲參數def_api,然後您將調用它作爲第一部分你的派生函數。事情是這樣的:

def self.def_api(function, parameters, return_value, &valid_args?)    
    api = Win32API.new 'user32', function, parameters, return_value 

    define_method(function.snake_case) do |*args| 
    if valid_args? and valid_args?.call(*args)    
     api.call *args 
    else 
     // raise argument error, etc 
    end           
    end 

end 

然後

def_api 'FindWindow', ['P', 'P'], 'L', { |args| return true if // API specific checks succeed } 

UPDATE:在提問的請求

&valid_args?添加更多的色彩是塊參數的名稱。和號前綴(&)是你如何告訴ruby你傳遞了一個塊。您只能將一個塊傳遞給方法,並且它必須是參數列表中的最後一個參數。問號後綴(?)只是Ruby編程中的一個約定,用於命名返回布爾值的函數。

如果塊傳遞你&block.call(args)

調用方法與塊參數調用它,你做這樣的事情:

method { |args| // block implementation } 

method do |args| 
    // block implementation 
end 

args是通過call method傳遞給塊。希望這可以幫助。

+0

所以{| args | ...}在def_api調用中的塊將充當args驗證器(即由valid_args調用)?對不起,我對紅寶石的認識有時並不那麼深入。另外,我有點困惑valid_args?.call(* args)你可以提供更多的洞察力,知道那裏發生了什麼? 感謝一噸的快速回答,非常感謝... – 2010-07-12 13:49:55

+0

Rad - 幫助噸。再次感謝您花時間解釋,非常感謝。 – 2010-07-12 14:28:55

相關問題