当没有提供args时,Ruby的* args导致seg错误

时间:2010-07-12 12:08:44

标签: ruby rspec args

我正在尝试使用Ruby在Windows中进行一些脚本化的GUI测试。我正在利用pragprog book的指导,我有点陷入困境。我已经考虑了一些代码来帮助重复映射win32api函数。代码如下:

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

...所以我可以使用该块以下列方式在模块中定义几个win32API:

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的情况下调用它,我就无法触摸* args - 但我可以使用args.length来查看它是空的。

为什么会导致seg错误而不是例外?通过类似的东西来解决这个问题是否可以接受。

  raise BadArgs if args.length == 0

又一个问题太长了 - 抱歉。

TIA! 鲍勃

1 个答案:

答案 0 :(得分:1)

它出现seg错误的可能原因是因为Win32API下面的某个地方缺少参数正在转换为一个或多个NULL指针解引用。

如果你要创建这样的函数,那么你应该考虑添加一个per-api-call,boolean-returns参数验证块(或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 }

更新:在提问者的请求中添加更多颜色

&valid_args?是块参数的名称。 &符号前缀(&)是告诉ruby您传递块的方式。您只能将一个块传递给方法,它必须是参数列表中的最后一个参数。问号后缀(?)只是Ruby编程中用于命名返回布尔值的函数的约定。

如果传递了一个块,则使用&block.call(args)

调用它

要使用块参数调用方法,请执行以下操作:

method { |args| // block implementation }

method do |args|
  // block implementation
end

args通过call method传递给该区块。希望这会有所帮助。