1

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

最初のテストではすべてが正常に機能し、2 番目のテストではセグ フォールトが発生します。引数なしでこれを呼び出すと、 *args に触れることができないようですが、 args.length を実行して、それが空であることを確認できます。

これにより、例外ではなくセグ フォールトが発生するのはなぜですか? これを次のような方法で解決することは受け入れられますか..

  raise BadArgs if args.length == 0

さらにもう 1 つの質問が長すぎます。申し訳ありません。

ティア!ボブ

4

1 に答える 1

1

セグメントの障害である可能性が高い理由はWin32API、引数の欠如の下のどこかが1つ以上のNULLポインター逆参照に変換されているためです。

このような関数を作成する場合は、API呼び出しごとにブール値を返す引数検証ブロック(またはラムダ)を引数として追加し、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?ブロックパラメータの名前です。アンパサンドプレフィックス(&)は、ブロックを渡すことをルビーに伝える方法です。メソッドに渡すことができるブロックは1つだけであり、引数リストの最後のパラメーターである必要があります。疑問符の接尾辞(?)は、ブール値を返す関数に名前を付けるためのRubyプログラミングの慣例にすぎません。

ブロックが渡された場合は、でそれを呼び出します&block.call(args)

ブロック引数を使用してメソッドを呼び出すには、次のようにします。

method { |args| // block implementation }

また

method do |args|
  // block implementation
end

args、を介してブロックに渡されcall methodます。お役に立てれば。

于 2010-07-12T13:06:10.713 に答える