Comment utilisez-vous Ruby / DL? Est-ce correct?

J’essaie d’écrire une interface entre RSPEC (BDD à saveur de rbuy) et une application Windows. L’application elle-même est écrite dans un langage obscur, mais elle dispose d’une API C pour fournir un access. J’ai opté pour Ruby / DL, mais j’ai des difficultés à faire fonctionner même l’appel le plus élémentaire d’une méthode DLL. Voici ce que j’ai jusqu’à présent, dans un fichier nommé 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 

Mes lectures jusqu’à présent suggèrent que c’est tout ce dont j’avais besoin pour commencer, alors j’ai écrit un exemple de 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 

Et quand couru …

 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 

La valeur de retour (13) est un code de retour réel, ce qui signifie une erreur, mais lorsque j’essaie d’append l’appel gTD_get_error_message à mon RSPEC, les parameters ne fonctionnent pas.

Est-ce que je vais dans la bonne direction et est-ce que quelqu’un peut indiquer la prochaine chose que je peux essayer?

Merci Brett


Un suivi de cette question, montrant la partie qui échoue lorsque j’essaie d’obtenir le message d’erreur de ma bibliothèque cible:

 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 

Je m’attends à ce que le message d’erreur soit renvoyé dans @msg, mais lorsque j’exécute le système,

 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. 

Et ceci si j’utilise un symbole (: msg) à la place:

 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 

Clairement, il me manque quelque chose à propos du passage de parameters entre ruby ​​et C, mais quoi?

    Le consensus général est que vous voulez éviter le plus possible la DL. La documentation (anglaise) est assez sommaire et l’interface est difficile à utiliser, sauf pour des exemples sortingviaux.

    L’interface C native de Ruby est BEAUCOUP plus facile à programmer. Vous pouvez également utiliser FFI, qui remplit un créneau similaire à DL, provient du projet rubinius et a récemment été porté sur un rbuy “normal”. Il a une interface plus agréable et est beaucoup moins pénible à utiliser:

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

    La valeur de retour (13) est un code de retour réel, ce qui signifie une erreur, mais lorsque j’essaie d’append l’appel gTD_get_error_message à mon RSPEC, les parameters ne fonctionnent pas.

    Cela pourrait aider de poster l’erreur au lieu du code qui a fonctionné 🙂

    En gros, une fois que vous commencez à avoir à gérer des pointeurs comme dans (int, char **), les choses deviennent laides.

    Vous devez allouer le pointeur de données pour l’écriture de msg, car otherise C n’aura nulle part où écrire les messages d’erreur. Utilisez DL.mallo.