Używanie kodu Rust z projektu C++ mam już sprawdzone ;), polega na wykorzystaniu FFI w celu zapewnienia bezpieczeństwa typów. Po stronie Rust, kod źródłowy obiektu dzielonego (DLL), z niego wyjdzie np. libdylib.so: #![crate_type = "dylib"]
extern crate libc;
use std::ffi::CStr;
#[no_mangle]
pub fn hello_world(name: *const libc::c_char) {
let buf_name = unsafe {
CStr::from_ptr(name).to_bytes()
};
let str_name = String::from_utf8(buf_name.to_vec()).unwrap();
println!("Hello, {}!", str_name);
}
Poprzez wykorzystanie specyfikatora "no_mangle", symbol dla funkcji hello_world będzie wyglądał tak, jak np. przy użyciu extern "C" w C++, czyli będzie miał wycięte informacje o typach, etc - "_hello_world". Taką DLL'kę lub obiekt dzielony można załadować standardowo, jak każdy inny obiekt. Po stronie C++: #include <iostream>
#include <dlfcn.h>
int main() {
void* lib = dlopen("./target/release/libdylib.so", RTLD_LAZY);
if(!lib) {
std::cout << "can't open libdylib.so\n";
return 1;
}
void* func = dlsym(lib, "hello_world");
if(!func) {
std::cout << "can't locate function hello_world()\n";
dlclose(lib);
return 1;
}
typedef void (*hello_world_fun)(const char* somestr);
hello_world_fun hello_world = (hello_world_fun) func;
hello_world("C++");
dlclose(lib);
return 0;
}
(dlopen to jest to samo co LoadLibrary, a dlsym to jest to samo co GetProcAddress). Wyjście programu: $ ./test
Hello, C++!
Na Linuxie można też zlinkować wygenerowany obiekt dzielony do exeka pisanego w C++, więc możliwe jest stworzenie takiego programu, wołającego funkcję z Rust'a bezpośrednio, bez potrzeby ładowania dynamicznego: #include <iostream>
#include <dlfcn.h>
extern "C" void hello_world(const char* ptr);
int main() {
hello_world("C++");
return 0;
}