c - sirve - ruby-< lang
¿Cómo se usa Ruby/DL? ¿Es esto correcto? (3)
El valor devuelto (13) es un código de retorno real, lo que significa un error, pero cuando intento agregar la llamada gTD_get_error_message a mi RSPEC, no puedo hacer que los parámetros funcionen.
Podría ayudar a publicar el error en lugar del código que funcionó :)
Básicamente, una vez que comienzas a tener que lidiar con punteros como en (int, char **), las cosas se ponen feas.
Estoy tratando de escribir una interfaz entre RSPEC (BDD con sabor a rubí) y una aplicación de Windows. La aplicación en sí está escrita en un lenguaje oscuro, pero tiene una API C para proporcionar acceso. Me he ido con Ruby / DL, pero estoy teniendo dificultades para que funcione la llamada más básica a un método DLL. Esto es lo que tengo hasta ahora, en un archivo llamado 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
Mi lectura hasta el momento sugiere que esto es todo lo que necesito para ponerme en marcha, así que escribí un ejemplo 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
Y cuando se ejecuta ...
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
El valor devuelto (13) es un código de retorno real, lo que significa un error, pero cuando intento agregar la llamada gTD_get_error_message a mi RSPEC, no puedo hacer que los parámetros funcionen.
¿Estoy yendo en la dirección correcta y alguien puede señalar lo siguiente que puedo intentar?
Gracias, Brett
Un seguimiento de esta pregunta, que muestra la parte que falla cuando trato de obtener el mensaje de error de mi biblioteca de destino:
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
Espero que el mensaje de error se devuelva en @msg, pero cuando se ejecuta, obtengo lo siguiente:
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.
Y esto si uso un símbolo (: msg) en su lugar:
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
Claramente me falta algo acerca de pasar parámetros entre ruby y C, ¿pero qué?
El consenso general es que desea evitar DL tanto como sea posible. La documentación (en inglés) es bastante incompleta y la interfaz es difícil de usar para todo menos para ejemplos triviales.
La interfaz Ruby native C es MUCHO más fácil de programar. O podría usar FFI, que llena un nicho similar a DL, originalmente proviene del proyecto Rubinius y recientemente ha sido portado al rubí "normal". Tiene una interfaz más agradable y es mucho menos doloroso de usar:
http://blog.headius.com/2008/10/ffi-for-ruby-now-available.html
Debe asignar el puntero de datos para que se escriba el mensaje, ya que otherise C no tendrá dónde escribir los mensajes de error. Use DL.mallo.