2017-10-02 90 views
5

Próbuję zbudować funkcje Octave w Rust. API Octave'a znajduje się w C++, więc wygenerowałem wiązania za pomocą rust-bindgen. Aktualnie pracuję nad problemami, które występują podczas próby wygenerowania bindings that include std::string. Byłoby miło, gdybym mógł pozostawić nieprzezroczysty i prawidłowy wskaźnik na C++ std::string. Czy byłoby możliwe zbudowanie funkcji użyteczności po stronie C++ za każdym razem, gdy potrzebowałem przejść w C++ std::string?Interakcja Rust z C++ std :: string

Byłem naiwny, kiedy po raz pierwszy spróbowałem tego. Jest to oczywiście błędne. Rdza std::ffi:CString dotyczy ciągów C, a nie C++. Znalazłem this recent blog pomocne przy porównywaniu dwóch. Moja pierwsza próba wygląda 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) 
} 

muszę przechodzić w nazwie funkcji i dokumentacji jako ciągów octave_dld_function_create. Szkoda, że ​​nie było CppString, którego mógłbym użyć zamiast tego. Wszelkie sugestie dotyczące postępowania?

+0

C++ producenci kompilatorów/stdlib nie mają tego pojęcia; Nie oczekiwałbym Rusta. ; -] (Aby było jasne, 'std :: string' jest mandowanym interfejsem, a nie wymaganą implementacją, a jeśli chcesz przekazać _anything_ według wartości, musisz przynajmniej znać jego rozmiar/układ). – ildjarn

+0

Próbuję na początku współpracować z GNU Octave na Ubuntu Linux. Kompilatorem jest gcc 6.3.0 z 'gcc -dumpversion', a stdlib to libstdC++. So.6 (libc6, x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 z' ldconfig -p | grep stdC++ '. https://stackoverflow.com/a/10355215/23059 –

+1

Czy jest to z definicją lub bez '_GLIBCXX_USE_CXX11_ABI'? ;-] Point is being, jeśli nie został właściwie wyabstrahowany w C++ - narzędziach budowania, robienie tego gdzie indziej ma bardzo małą szansę. Na przykład.mój system ma dostępne libC++, libstdC++ i Dinkumware stdlibs. – ildjarn

Odpowiedz

3

Jest to klasyczny problem FFI i roztwór jest użycie "klepsydry" wzorem: A Język < => Wspólne ABI < => Język B.

To może być możliwe, oczywiście, evolve bindgen, aby wiernie odtworzyć ABI w C++, ale w praktyce wymagałoby to pełnego kompilatora C++, który jest prawdopodobnie zbyt dużym wysiłkiem.

Korzystając z projektu "klepsydry", każdy z języków z trudnym ABI wykorzystuje własny wyspecjalizowany zestaw narzędzi do konwersji na konkretny znany ABI. W takim przypadku będzie to C++ < => C < => Rdza.

Możliwe rozwiązanie polega na utworzeniu biblioteki opakowującej C wokół interfejsu API C++, a następnie użycie w tym celu bindgen. Tak właśnie robią projekty LLVM i Clang.

Jest to najprostsze rozwiązanie, a projekt Octavo może bardzo dobrze zechcieć zintegrować taką fasadę octavo-c w drzewie (co zawsze najlepiej zagwarantować jej aktualność).


Innym rozwiązaniem byłoby stworzenie C++ biblioteki towarzysz bindgen, który dba o zapewnienie C-ABI dla wspólnej C++ typów (takich jak std::string). Byłoby to bardziej trudne przedsięwzięcie, zwłaszcza że:

  • C nie ma leków generycznych, dlatego Szablony C++ musiałyby być out-of-zakres, lub pre-instancji szablonów musiałby być opakowane pojedynczo ,
  • C nie wie jak wywołać przenieść lub skopiować konstruktorów, więc chyba C++ typy są już POD, muszą być manipulowane przez mętny wskaźnik,
  • C nie wiem ...