2015-06-24 16 views
9

Tôi đang cố truyền một chuỗi trong Ruby thành một tệp thực thi rỉ sét, thao tác nó và chuyển chuỗi thao tác trở lại.Chuỗi Ruby bị rỉ sét và trở lại lần nữa

Cho đến nay tôi có thể chuyển chuỗi vào và gửi lại nhưng tôi không biết cách chuyển đổi thành chuỗi gỉ, thao tác và sau đó chuyển nó trở lại ruby. Dưới đây là những gì tôi có cho đến nay:

// lib.rs 
use std::ffi::CStr; 

#[no_mangle] 
pub extern fn return_string(test_str: &CStr) -> &CStr { 
    // working funciton 
    test_str 
} 

#[no_mangle] 
pub extern fn manipulate_and_return_string(mystr: &CStr) -> &CStr { 
    // mystr type == &std::ffi::c_str::CStr 
    // println!("{:?}", mystr); => std::ffi::c_str::CStr` cannot be formatted using `:?` 
    let cstr = mystr.to_bytes_with_nul(); 
    // println!("{:?}", mystr); => [] 
    // cstr type == &[u8] 
    let ptr = cstr.as_ptr(); 
    // ptr type == *const u8 
    // println!("{:?}", mystr); => 0x7fd898edb520 
    let str_slice: &str = std::str::from_utf8(cstr).unwrap(); 
    // str type == &str 
    // println!("{:?}", mystr); => "" 
    let str_buf: String = str_slice.to_owned(); 
    // str_bug == collections::string::String 
    // println!("{:?}", mystr); => "" 
} 
# rust.rb 
require 'ffi' 

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

    attach_function :return_string, [:string], :string 
    attach_function :manipulate_and_return_string, [:string], :string 
end 
+7

bình luận nhanh: có hai vấn đề ngay lập tức với điều này. Thứ nhất, 'CStr' ** không phải là loại an toàn FFI ** và không nên được sử dụng như thế này. Bạn nên sử dụng '* const libc :: c_char'. Thứ hai, câu trả lời phụ thuộc hoàn toàn vào ai, chính xác, sở hữu chuỗi kết quả. Ruby có quản lý nó không? Nếu vậy, làm thế nào? Heap nào cần phải được cấp phát? Rust có còn sở hữu nó không? Nếu vậy, làm thế nào để bạn cung cấp một chức năng dọn dẹp? Tất cả những gì tôi có thể đề nghị là tìm hiểu cách làm điều này trong C, sau đó chỉ cần làm theo cách đó trong Rust. –

+2

Ngoài ra, hãy xem http://stackoverflow.com/q/30510764/155423 vì nó bao gồm tất cả các phần quan trọng. Việc thích ứng với Ruby thật dễ dàng tại thời điểm đó. – Shepmaster

+1

http://clalance.blogspot.ca/2011/01/writing-ruby-extensions-in-c-part-8.html sẽ hữu ích, vì sẽ là https://github.com/ruby/ruby/blob /trunk/doc/extension.rdoc –

Trả lời

4

Nhờ một số hướng dẫn từ Steve Klabnik, shepmasterDK tôi đã tìm ra cách viết một hàm chuỗi concat bên ngoài trong Rust và sử dụng nó trong Ruby.

// lib.rs 
#![feature(libc)] 
#![feature(cstr_to_str)] 
#![feature(cstr_memory)] 
extern crate libc; 
use std::ffi::{CStr,CString}; 

#[no_mangle] 
pub extern fn concat(s1: *const libc::c_char, s2: *const libc::c_char) -> *const libc::c_char { 
    let s1_cstr = unsafe { CStr::from_ptr(s1) }; // &std::ffi::c_str::CStr 
    let s2_cstr = unsafe { CStr::from_ptr(s2) }; // &std::ffi::c_str::CStr 
    let s1_and_str = s1_cstr.to_str().unwrap(); // &str 
    let s2_and_str = s2_cstr.to_str().unwrap(); // &str 

    let mut s1_string = s1_and_str.to_string(); // collections::string::String 

    s1_string.push_str(s2_and_str); 
    // s1_string + s2_and_str); // same thing 

    let concated_string = CString::new(s1_string).unwrap(); // std::ffi::c_str::CString 

    concated_string.into_ptr() // const i8 
} 
# rust.rb 
require 'ffi' 

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

    attach_function :concat, [:string, :string], :string 
end 
#calling the function in Ruby 

Rust.concat('This is a ', 'cohesive sentence') # => 'This is a cohesive sentence' 
Các vấn đề liên quan