2008-11-06 64 views
3

我正在嘗試編寫RSPEC(ruby flavored BDD)和Windows應用程序之間的接口。應用程序本身是用一種晦澀的語言編寫的,但它有一個C API來提供訪問。我已經使用了Ruby/DL,但即使是最基本的調用DLL方法的工作也有困難。這裏是我到目前爲止,在一個名爲gt4r.rb:你如何使用Ruby/DL?這是正確的嗎?

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. 

這如果我使用一個符號(:味精),而不是:

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,但什麼之間傳遞參數?

回答

7

總體共識是你想避免DL儘可能多。 (英文)文檔非常粗略,界面很難用於其他任何事情,除了微不足道的例子。

Ruby本地C接口更容易編程。或者你可以使用FFI,它與DL完全類似,它最初來自rubinius項目,最近被移植到「普通」ruby。它有一個更好的界面和更痛苦的使用:

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

+0

我到目前爲止閱讀的FFI聽起來很有趣。我試試看... – Brett 2008-11-07 14:16:49

+0

hmmm ...不適用於windows – Brett 2008-11-07 15:10:01

1

的返回值(13)是一個實際的 返回代碼,這意味着一個錯誤,但是 當我嘗試添加 gTD_get_error_message調用我的 RSPEC,我無法獲得參數 的工作。

它可以幫助發佈的錯誤,而不是代碼工作:)

基本上,一旦你開始不得不面對指針在(INT,字符**),事情變得醜陋。

0

您需要爲要寫入的msg分配數據指針,因爲其他C無法寫入錯誤消息。使用DL.mallo。