ruby ffi

ruby - ¿Es posible usar Fiddle para pasar o devolver una estructura a código nativo?



ffi (1)

He revisado la documentación de Fiddle y, como puedo ver, no es posible, ya que incluso en la definición de la función central Fiddle::Function.new requiere Fiddle::CParser pueda manejar Fiddle::CParser . He hecho varias pruebas y, para hacer que funcione, tuve que transformar tu código en algo como esto:

prueba2.c

#include <stdio.h> #include <stdlib.h> typedef struct { char *data; char *more_data; size_t len; } my_thing_t; my_thing_t *returns_a_struct(void){ my_thing_t *structure = malloc(sizeof(my_thing_t)); structure->data = "test2"; structure->more_data = "I am more data"; structure->len = 5; return structure; };

irb

require ''fiddle'' require ''fiddle/import'' module Testmd extend Fiddle::Importer dlload ''./test2.dll'' RetStruct = struct [''char *data'',''char *more_data'',''size_t len''] extern ''RetStruct* returns_a_struct(void)'' end include Testmd 2.2.1 :013 > res = Testmd::returns_a_struct(nil) => #<Fiddle::Pointer:0x00000000b12a10 ptr=0x00000000e066b0 size=0 free=0x00000000000000> 2.2.1 :014 > s = RetStruct.new(res) => #<Testmd::RetStruct:0x00000000c3e9e8 @entity=#<Fiddle::CStructEntity:0x000000007f0ad0 ptr=0x00000000e066b0 size=24 free=0x00000000000000>> 2.2.1 :015 > s.data.to_s => "test2" 2.2.1 :016 > s.more_data.to_s => "I am more data" 2.2.1 :017 > s.len => 5

Lo que descubrí es que Fiddle puede operar con tipos simples pero necesita que se pasen tipos de struct y de union usando referencias. Todavía tiene envoltorios para estas clases. Además, estos envoltorios se heredan de Fiddle::Pointer lo que nos lleva a la conclusión de que quieren que usemos punteros para estos tipos de datos.

Si desea más detalles sobre esto o desea agregar esta funcionalidad, puede ir a través de su repositorio git .

Me gustaría usar Fiddle para acceder a una biblioteca nativa compilada desde el código Rust. La representación en C de la estructura es muy simple, es solo un puntero y una longitud:

typedef struct { char *data; size_t len; } my_thing_t; // Example function that somehow accepts a struct void accepts_a_struct(my_thing_t thing); // Example function that somehow returns a struct my_thing_t returns_a_struct(void);

Sin embargo, todos los ejemplos que puedo encontrar aceptan o devuelven punteros a estructuras, y no las estructuras en sí. Me gustaría evitar la doble indirección si es posible.

He tomado prestado un ejemplo de la documentación de Fiddle::Importer . Sin embargo, no veo cómo llamar correctamente al método extern con una estructura en lugar de un puntero a una estructura:

require ''fiddle'' require ''fiddle/import'' module LibSum extend Fiddle::Importer dlload ''./libsum.so'' extern ''double sum(double*, int)'' extern ''double split(double)'' end

Nota

El violín no es lo mismo que la gema FFI . Fiddle es un componente de la biblioteca estándar de Ruby y no se proporciona como una gema separada. Estas preguntas relacionadas se refieren a la gema de FFI, y no a Fiddle:

  • ¿Cómo envolver la función en el método Ruby FFI que toma struct como argumento?
  • ¿Cómo especifico una estructura como el valor de retorno de una función en RubyFFI?