2017-10-02 20 views
5

Tôi đang cố gắng xây dựng các hàm Octave trong Rust. API của Octave là trong C++, vì vậy tôi đã tạo ra các ràng buộc bằng cách sử dụng rust-bindgen. Tôi hiện đang làm việc thông qua các vấn đề xảy ra khi cố gắng tạo ra bindings that include std::string. Sẽ rất tuyệt nếu tôi có thể để con trỏ mờ và hợp lệ đến số C++ std::string. Nó có thể được xây dựng một chức năng tiện ích trên bên C++ bất cứ lúc nào tôi cần phải vượt qua trong một C++ std::string?Rust interop với C++ std :: string

Tôi đã ngây thơ khi lần đầu tiên tôi thử điều này. Rõ ràng là sai. A Rust std::ffi:CString là dành cho chuỗi C, không phải chuỗi C++. Tôi thấy this recent blog hữu ích khi so sánh hai. Nỗ lực đầu tiên của tôi trông like this:

#![allow(non_snake_case)] 
#![allow(unused_variables)] 

extern crate octh; 

// https://thefullsnack.com/en/string-ffi-rust.html 
use std::ffi::CString; 

#[no_mangle] 
pub unsafe extern "C" fn Ghelloworld (shl: *const octh::root::octave::dynamic_library, relative: bool) -> *mut octh::root::octave_dld_function { 
    let name = CString::new("helloworld").unwrap(); 
    let pname = name.as_ptr() as *const octh::root::std::string; 
    std::mem::forget(pname); 

    let doc = CString::new("Hello World Help String").unwrap(); 
    let pdoc = doc.as_ptr() as *const octh::root::std::string; 
    std::mem::forget(pdoc); 

    octh::root::octave_dld_function_create(Some(Fhelloworld), shl, pname, pdoc) 
}  

pub unsafe extern "C" fn Fhelloworld (args: *const octh::root::octave_value_list, nargout: ::std::os::raw::c_int) -> octh::root::octave_value_list { 
    let list_ptr = ::std::ptr::null_mut(); 
    octh::root::octave_value_list_new(list_ptr); 
    ::std::ptr::read(list_ptr) 
} 

tôi cần phải vượt qua trong tên hàm và tài liệu như dây đàn để octave_dld_function_create. Tôi muốn có một CppString mà tôi có thể sử dụng để thay thế. Mọi đề xuất về cách tiến hành?

+0

C++ các nhà cung cấp trình biên dịch/stdlib không có điều này; Tôi sẽ không mong đợi Rust đến. ; -] (Để rõ ràng, 'std :: string' là giao diện bắt buộc, không phải là thực thi bắt buộc và nếu bạn muốn chuyển _anything_ theo giá trị, ít nhất bạn cần phải biết kích thước/bố cục của nó.) – ildjarn

+0

Tôi đang cố gắng để tương tác với GNU Octave trên Ubuntu Linux để bắt đầu. Trình biên dịch là gcc 6.3.0 từ 'gcc -dumpversion' và stdlib là libstdC++. So.6 (libc6, x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 từ' ldconfig -p | grep stdC++ '. https://stackoverflow.com/a/10355215/23059 –

+1

Và có hay không có '_GLIBCXX_USE_CXX11_ABI' được xác định? ; -] Điểm là, nếu nó không được trừu tượng đúng trong C++ - công cụ xây dựng, làm như vậy ở nơi khác có một cơ hội rất mỏng. Ví dụ.hệ thống của tôi có sẵn libC++, libstdC++ và Dinkumware stdlibs. – ildjarn

Trả lời

3

Đây là một vấn đề FFI cổ điển và các giải pháp là sử dụng một "hồ cát" thiết kế: Ngôn ngữ Một < => Common ABI < => Ngôn ngữ B.

Nó có thể là có thể, tất nhiên, để phát triển bindgen để nó có thể tái tạo một cách trung thực một C++ ABI, nhưng trong thực tế nó sẽ đòi hỏi một trình biên dịch C++ đầy đủ, có lẽ là quá nhiều nỗ lực.

Sử dụng thiết kế "kính", mỗi ngôn ngữ có ABI khó sử dụng chuỗi công cụ chuyên dụng của riêng mình để chuyển đổi thành ABI nổi tiếng cụ thể. Trong trường hợp này, nó sẽ là C++ < => C < => Rust.

Một giải pháp khả thi là tạo thư viện trình bao bọc C quanh API C++ và sau đó sử dụng bindgen trên đó. Đây là những gì các dự án LLVM và Clang làm.

Đây là giải pháp đơn giản nhất, và dự án Octavo có thể rất sẵn sàng tích hợp một mặt tám octavo-c trong cây (luôn luôn là tốt nhất để đảm bảo nó được cập nhật).


Một giải pháp khác là tạo ra một thư viện C++ đồng cho bindgen, mà sẽ chăm sóc của việc cung cấp một C-ABI cho C++ phổ biến các loại (như std::string). Đây sẽ là một nỗ lực khó khăn hơn, đặc biệt là từ:

  • C không có generics, vì vậy mẫu C++ sẽ phải nằm ngoài phạm vi hoặc mẫu được tạo trước sẽ phải được gói mỗi lần ,
  • C không biết làm thế nào để gọi di chuyển hoặc sao chép constructor, vì vậy trừ khi C++ loại đã PODs, họ phải được thao tác thông qua con trỏ đục,
  • C không biết ...
Các vấn đề liên quan