Shared/Dynamic libraries are just libraries. You need to write a header file that matches the prototypes you export for use in other languages. Since the export will be C (due to the C++ ABI being a problem), you'll want to write out the prototypes as C types.
It really depends on what you wrote, and I can't remember all of the details off the top of my head, but taking the example and modifying it ever so slightly:
use std::thread;
#[no_mangle]
pub extern fn process(count: usize) {
let handles: Vec<_> = (0..count).map(|_| {
thread::spawn(|| {
let mut x = 0;
for _ in 0..5_000_000 {
x += 1
}
x
})
}).collect();
for h in handles {
println!("Thread finished with count={}",
h.join().map_err(|_| "Could not join a thread!").unwrap());
}
}
I just spun up a new crate and added:
[lib]
name = "dlltest"
crate-type = ["dylib"]
And a quick, hacky, MSVC application to test it:
// Cross-platform bootstrap
#if defined(_WIN32) || defined(_WIN64)
# ifdef __GNUC__
# define API_EXPORT __attribute__ ((dllexport))
# define API_IMPORT __attribute__ ((dllimport))
# else
# define API_EXPORT __declspec(dllexport)
# define API_IMPORT __declspec(dllimport)
# endif
# define API_STATIC
#else
# ifdef __GNUC__
# define API_EXPORT __attribute__((visibility ("default")))
# define API_IMPORT __attribute__((visibility ("default")))
# else
# define API_EXPORT
# define API_IMPORT
# endif
# define API_STATIC
#endif
extern "C" {
API_IMPORT void process(size_t count);
}
int main(int argc, char **argv)
{
process(15);
return 0;
}
The ifdef in the C++ is probably out of date, I pulled it from an old snippet to bootstrap because I didn't want to restrict to a single platform. Chances are you want attribute on everything these days, but since it's from when I used to use g++ on Linux (and almost never Clang), it's probably dated.
Edit: To be clear, the "header" content is this:
extern "C" {
API_IMPORT void process(unsigned int count);
}
I took the prototype from Rust and made it into a C prototype. There's nothing particularly special about it, save that usize becomes unsigned int, and the return value not being specified in Rust is void. The rest of what I didn't say is basic C++/Rust programming.