Diciamo che questa è la libreria che si desidera utilizzare nello script rubino, lo chiamano my_c_lib.c
:
#include <stdlib.h>
double *my_function(double array[], int size)
{
int i = 0;
double *new_array = malloc(sizeof(double) * size);
for (i = 0; i < size; i++) {
new_array[i] = array[i] * 2;
}
return new_array;
}
È possibile compilare in questo modo:
$ gcc -Wall -c my_c_lib.c -o my_c_lib.o
$ gcc -shared -o my_c_lib.so my_c_lib.o
Ora, è pronto a utilizzare nel nel codice ruby (my_c_lib.rb
):
require 'ffi'
module MyModule
extend FFI::Library
# Assuming the library files are in the same directory as this script
ffi_lib "./my_c_lib.so"
attach_function :my_function, [:pointer, :int], :pointer
end
array = [4, 6, 4]
size = array.size
offset = 0
# Create the pointer to the array
pointer = FFI::MemoryPointer.new :double, size
# Fill the memory location with your data
pointer.put_array_of_double offset, array
# Call the function ... it returns an FFI::Pointer
result_pointer = MyModule.my_function(pointer, size)
# Get the array and put it in `result_array` for use
result_array = result_pointer.read_array_of_double(size)
# Print it out!
p result_array
Ed ecco il risultato dell'esecuzione dello script:
$ ruby my_c_lib.rb
[8.0, 12.0, 8.0]
Una nota sulla gestione della memoria ... dalla documentazione https://github.com/ffi/ffi/wiki/Pointers:
La FFI :: classe MemoryPointer alloca la memoria nativa con garbage collection automatica come dolcificante. Quando un MemoryPointer esce dal campo di applicazione, la memoria viene liberata come parte del processo di garbage collection.
Quindi non si dovrebbe chiamare direttamente pointer.free
. Inoltre, proprio per verificare se si doveva liberi manualmente result_pointer
, ho chiamato result_pointer.free
dopo la stampa l'estrazione della matrice e ottenuto questo avvertimento
warning: calling free on non allocated pointer #<FFI::Pointer address=0x007fd32b611ec0>
così sembra che non si dispone alla libera manualmente result_pointer
neanche.