【问题标题】:How do you use Ruby/DL? Is this right?你如何使用 Ruby/DL?这是正确的吗?
【发布时间】:2010-09-21 02:38:36
【问题描述】:

我正在尝试编写 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 之间传递参数时遗漏了一些东西,但是什么?

【问题讨论】:

    标签: c ruby interface rspec rubydl


    【解决方案1】:

    普遍的共识是您希望尽可能避免深度学习。 (英文)文档非常粗略,界面很难用于除琐碎示例之外的任何内容。

    Ruby 原生 C 接口更容易编程。或者您可以使用 FFI,它填补了与 DL 类似的利基,最初来自 rubinius 项目,最近被移植到“普通”ruby。它有一个更好的界面,使用起来也不会那么痛苦:

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

    【讨论】:

    • ffi gem 现在适用于 Windows [至少 mingw 与 devkit]
    • FFI 绝对适用于 Windows (Ruby 1.9.3) Here's a solution 使用 FFI 从 Ruby 调用 C 函数
    【解决方案2】:

    返回值 (13) 是一个实际的 返回码,表示错误,但是 当我尝试添加 gTD_get_error_message 调用我的 RSPEC,我无法获取参数 工作。

    它可能有助于发布错误而不是有效的代码:)

    基本上,一旦你开始不得不像 (int, char **) 那样处理指针,事情就会变得丑陋。

    【讨论】:

    • 太真实了 - 我试图避免丑陋的部分。 :) 我会问一个解决参数不起作用的后续问题。干杯,布雷特
    【解决方案3】:

    您需要为要写入的 msg 分配数据指针,因为否则 C 将无处可写错误消息。使用 DL.mallo。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-12
      • 2018-08-13
      • 2015-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多