How do you use Ruby / DL? It is right?

I am trying to write an interface between RSPEC (Ruby BDD Flavor) and a Windows application. The application itself is written in an obscure language, but it does have a C API that provides access. I went with Ruby / DL, but I had difficulty getting even the most basic DLL method call to work. Here is what I still have in the gt4r.rb file:

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 

My reading so far suggests that this is all I need to get started, so I wrote an RSPEC example:

 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 

And at startup ...

 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 

The return value (13) is the actual return code, which means an error, but when I try to add the gTD_get_error_message call to my RSPEC, I cannot get the parameters to work.

I am heading in the right direction and can anyone point out the following that I can try?

Thanks Brett


Follow this question, showing the part that fails when I try to get an error message from my target library:

 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 

I expect the error message to be returned in @msg, but when I start, I get the following:

 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 support team for more information. 

And if I use the symbol (: msg) instead:

 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 

It's clear that I'm missing something about passing parameters between ruby ​​and C, but what?

+3
source share
3 answers

The general consensus is that you want to avoid DL as much as possible. The English documentation is pretty sketchy, and the interface is hard to use for anything other than trivial examples.

The C interface of Ruby native MUCH is much easier to program. Or you can use FFI, which fills a similar niche for DL, originally comes from the rubinius project and has recently been migrated to a β€œregular” ruby. It has a more user-friendly interface and is much less painful to use:

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

+7
source

The return value (13) is the actual return code, which means an error, but when I try to add a gTD_get_error_message call to my RSPEC, I cannot get the parameters to work.

This may help post an error instead of code that worked :)

Basically, as soon as you start dealing with pointers, as in (int, char **), everything becomes ugly.

+1
source

You need to highlight the data pointer for the msg message, since it will not write error messages in another C. Use DL.mallo.

0
source

Source: https://habr.com/ru/post/1444604/


All Articles