Как вы используете Ruby / DL? Это правильно? - PullRequest
3 голосов
/ 06 ноября 2008

Я пытаюсь написать интерфейс между RSPEC (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, я не могу заставить параметры работать.

Я направляюсь в правильном направлении, и может ли кто-нибудь указать на следующее, что я могу попробовать?

Спасибо, Brett


Продолжение этого вопроса, показывающее, что происходит сбой при попытке получить сообщение об ошибке из целевой библиотеки:

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, но что?

Ответы [ 3 ]

7 голосов
/ 06 ноября 2008

По общему мнению, вы хотите как можно больше избегать DL. (Английская) документация довольно схематична, и интерфейс трудно использовать для чего-либо, кроме тривиальных примеров.

Интерфейс Ruby native C НАМНОГО проще программировать. Или вы могли бы использовать FFI, который заполняет аналогичную нишу для DL, изначально происходил из проекта rubinius и недавно был перенесен на «нормальный» рубин. Он имеет более приятный интерфейс и гораздо менее болезненный в использовании:

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

1 голос
/ 06 ноября 2008

Возвращаемое значение (13) является фактическим код возврата, означающий ошибку, но когда я пытаюсь добавить gTD_get_error_message вызов моего RSPEC, я не могу получить параметры работа.

Это может помочь опубликовать сообщение об ошибке вместо кода, который работал :)

По сути, как только вы начинаете иметь дело с указателями, как в (int, char **), все становится ужасно.

0 голосов
/ 22 января 2009

Вам нужно выделить указатель данных для msg для записи, так как в другом случае C некуда будет писать сообщения об ошибках. Используйте DL.mallo.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...