I am trying to create a shared object I can load into R that calls Rust functions by way of R's C API. To call Rust from C, I am following this blog post. My problem arises when I try to create the shared library and link to the Rust library. The linker complains that it can't find my Rust function. I am quite new to compiled languages and have given this a couple days' worth of effort before turning to SO. In that time I have learned a lot about compiler flags and yet come no closer to a solution. I think it may be something obvious.
My C++ code:
#include "Rinternals.h"
#include "R.h"
#include "treble.h"
// test.cpp
extern "C" {
SEXP triple(SEXP val) {
int32_t ival = *INTEGER(val);
Rprintf("9 tripled is %d\n", treble(ival));
return R_NilValue;
}
}
treble.h:
#include <stdint.h>
int32_t treble(int32_t value);
My Rust code:
#![crate_type = "dylib"]
#[no_mangle]
pub extern fn treble(value: i32) -> i32 {
value * 3
}
This is what I'm doing on the command line:
$ rustc glue.rs
$ g++ -shared test.cpp -o test.so -I/Library/Frameworks/R.framework/Headers -L/Library/Frameworks/R.framework/Libraries -L. -lR -lglue
Undefined symbols for architecture x86_64:
"treble(int)", referenced from:
_triple in test-dac64b.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Inspecting the object file that rust creates:
$ nm -gU libglue.dylib
...
0000000000001750 T _treble
In the C++ code, you need to declare the Rust function (which is available via the C ABI) as
extern "C"
.treble.h
The error you are getting is because the C++ compiler is name mangling the method
treble
before attempting to link against it.extern "C"
disables the mangling.Additionally, your Rust FFI code should always use the types from the libc crate; in your case you want
libc::int32_t
.