2010-07-12 78 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

相关问题