Search code examples
c++rustg++ldffi

How can I link a C++ program to a Rust program, then link that Rust program back to the C++ program? (cpp -> rust -> cpp)


I'm trying to link from Cpp to Rust, then from that Rust program, back to the original Cpp program.

(This might be a xy problem, so what I want to do is have a game written in cpp load mods written in rust. So I figure that the cpp would load the rust code, then to register items etc rust would call functions in the cpp game.)

But for now I am just using a quick testing environment:

Cpp files:

//main.cpp
#include "rust.h"
#include "main.h"
#include <stdio.h>

int main() {
        hello();
        print(100, 1.6, true);
        return 0;
}

void cpp() {
        printf("hello from cpp");
}

// main.h
void cpp();
// rust.h
// generated with cbindgen
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>

extern "C" {

void hello();

void print(int32_t a, float b, bool c);

} // extern "C"


Rust files:

// lib.rs
mod cpp;

#[no_mangle]
pub extern fn hello() {
    println!("hello from rust");
}

#[no_mangle]
pub extern fn print(a: i32, b: f32, c: bool) {
    println!("int: {}, float: {}, bool: {}", a, b, c);
    unsafe { cpp::cpp(); }
}
// cpp.rs
/* automatically generated by rust-bindgen 0.65.1 */

extern "C" {
    pub fn cpp();
}

Then I compile the Rust using with the crate-type of dylib so it outputs a .so file. To compile the cpp I use (the rust program's name is external):

g++ -L ./external/target/debug/ -Wall main.cpp -l external

Which errors with the message:

/usr/bin/ld: ./external/target/debug//libexternal.so: undefined reference to `cpp'
collect2: error: ld returned 1 exit status

If I remove the references to cpp in the rust programs so the flow is just cpp -> rust everything compiles just fine. It's just when the references to cpp are in rust, making the flow: cpp -> rust -> cpp that it breaks.

Hopefully this is enough information :)



Solution

  • C++ like Rust mangles it's exported symbols by default, to avoid it you have to declare cpp() to use the C ABI with extern "C":

    
    extern "C" void cpp() {
        printf("hello from cpp");
    }
    

    and in the header main.h as well.