3

RSPEC (Ruby フレーバーの BDD) と Windows アプリケーションの間のインターフェイスを作成しようとしています。アプリケーション自体はあいまいな言語で書かれていますが、アクセスを提供する C API があります。私は Ruby/DL を使用しましたが、DLL メソッドへの最も基本的な呼び出しでさえ機能させるのに苦労しています。gt4r.rb と呼ばれるファイルで、これまでに持っているものを次に示します。

require 'dl/import'

module Gt4r
  extend DL::Importable
  dlload 'c:\\gtdev\\r321\\bin\\gtvapi'

  # GTD initialization/termination functions
  extern 'int GTD_init(char *[], char *, char *)'
  extern 'int GTD_initialize(char *, char *, char *)'
  extern 'int GTD_done(void)'
  extern 'int GTD_get_error_message(int, char **)'
end

これまでの私の読書は、これが必要なすべてであることを示唆しているので、RSPEC の例を書き上げました。

require 'gt4r'

@@test_environment = "INCLUDE=C:\\graphtalk\\env\\aiadev\\config\\aiadev.ini"
@@normal_user = "BMCHARGUE"

describe Gt4r do
  it 'initializes' do
      rv = Gt4r.gTD_initialize @@normal_user, @@normal_user, @@test_environment
      rv.should == 0
  end
end

そして走ると…

C:\code\GraphTalk>spec -fs -rgt4r gt4r_spec.rb

Gt4r
- initializes (FAILED - 1)

1)
'Gt4r initializes' FAILED
expected: 0,
     got: 13 (using ==)
./gt4r_spec.rb:9:

Finished in 0.031 seconds

1 example, 1 failure

戻り値 (13) は実際の戻りコードであり、エラーを意味しますが、gTD_get_error_message 呼び出しを RSPEC に追加しようとすると、パラメーターが機能しません。

私は正しい方向に進んでいますか?次に試すことができることを誰かが指摘できますか?

ありがとう、ブレット


この質問のフォローアップで、ターゲット ライブラリからエラー メッセージを取得しようとすると失敗する部分を示します。

require 'gt4r'

@@test_environment = "INCLUDE=C:\\graphtalk\\env\\aiadev\\config\\aiadev.ini"
@@normal_user = "BMCHARGUE"

describe Gt4r do
  it 'initializes' do
      rv = Gt4r.gTD_initialize @@normal_user, @@normal_user, @@test_environment
      Gt4r.gTD_get_error_message rv, @msg
      @msg.should == ""
      rv.should == 0
  end
end

@msg でエラー メッセージが返されることを期待していますが、実行すると次のようになります。

Gt4r
(eval):5: [BUG] Segmentation fault
ruby 1.8.6 (2008-08-11) [i386-mswin32]


This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

代わりにシンボル (:msg) を使用すると、次のようになります。

C:\code\GraphTalk\gt4r_dl>spec -fs -rgt4r gt4r_spec.rb

Gt4r
- initializes (ERROR - 1)

1)
NoMethodError in 'Gt4r initializes'
undefined method `to_ptr' for :msg:Symbol
(eval):5:in `call'
(eval):5:in `gTD_get_error_message'
./gt4r_spec.rb:9:

Finished in 0.046 seconds

1 example, 1 failure

明らかに、Ruby と C の間でパラメーターを渡すことについて何かが欠けていますが、何ですか?

4

3 に答える 3

7

一般的なコンセンサスは、DLをできるだけ避けたいということです。(英語の) ドキュメントは非常に大ざっぱで、インターフェースは些細な例以外には使いにくいです。

Ruby ネイティブ C インターフェイスは、プログラミングがはるかに簡単です。または、DL と同様のニッチを埋める FFI を使用することもできます。これは、もともと rubinius プロジェクトから来ており、最近「通常の」ruby に移植されました。より優れたインターフェースを備えており、使用するのがはるかに苦痛ではありません。

http://blog.headius.com/2008/10/ffi-for-ruby-now-available.html

于 2008-11-06T17:59:28.093 に答える
1

戻り値 (13) は実際の戻りコードであり、エラーを意味しますが、gTD_get_error_message 呼び出しを RSPEC に追加しようとすると、パラメーターが機能しません。

機能したコードの代わりにエラーを投稿するのに役立つ場合があります:)

基本的に、(int, char **) のようにポインターを処理しなければならなくなると、事態は悪化します。

于 2008-11-06T18:03:51.627 に答える
0

otherise C にはエラー メッセージを書き込む場所がないため、msg が書き込まれるデータ ポインターを割り当てる必要があります。DL.mallo を使用します。

于 2009-01-22T08:15:50.367 に答える