Rust Vec for Ruby Array with FFI Segfaults

I'm trying to return a structure that can be converted to a Ruby array from an external rust function, but when I try to call the structs #to_a method, I get a segfault.

use libc::size_t;
#[repr(C)]
pub struct Array {
    len: libc::size_t,
    data: *const libc::c_void,
}

impl Array {
    fn from_vec<T>(mut vec: Vec<T>) -> Array {

        vec.shrink_to_fit();

        let array = Array { data: vec.as_ptr() as *const libc::c_void, len: vec.len() as libc::size_t };

        mem::forget(vec);

        array
    }
}

#[no_mangle]
pub extern fn get_links(url: *const libc::c_char) -> Array {

  // Get links

  let mut urls: Vec<String> = vec![];

  // push strings into urls vec

  // urls => collections::vec::Vec<collections::string::String>

  Array::from_vec(urls)
}

      

require 'ffi'

module Rust
  extend FFI::Library
  ffi_lib './bin/libembed.dylib'

  class NodesArray < FFI::Struct
      layout :len,    :size_t, # dynamic array layout
             :data,   :pointer #

      def to_a
          self[:data].get_array_of_string(0, self[:len]).compact
      end
  end

  attach_function :get_links, [:string], NodesArray.by_value
end

      

When I try to use this function in ruby ​​it will return Fii :: NodesArray. I can also get len ​​and data from a struct. Only when I call #to_a is it segfaults.

+3


source to share


2 answers


The problem noted by Adrian was that I was inserting lines into Vec. FFI needs *const libc::c_char

which can be converted from String

.



let mut urls: Vec<*const libc::c_char> = vec![];

urls.push(CString::new(string_var.value.to_string()).unwrap().into_raw());

      

+2


source


It seems to be FFI::Pointer#get_array_of_string

bugging (or it just doesn't do what I think it does). Your code works for me if I change this line:

self[:data].get_array_of_string(0, self[:len]).compact

      



:

Array.new(self[:len]) {|i| self[:data].read_pointer[i * FFI::Pointer::SIZE].read_string }

      

+1


source







All Articles