Skip to content

Add simple C++ to Rust interop example with Makefile build script - #29

Merged
teor2345 merged 9 commits into
rustfoundation:mainfrom
TG199:main
Apr 6, 2026
Merged

Add simple C++ to Rust interop example with Makefile build script#29
teor2345 merged 9 commits into
rustfoundation:mainfrom
TG199:main

Conversation

@TG199

@TG199 TG199 commented Mar 23, 2026

Copy link
Copy Markdown
Contributor

Add example demonstrating C++ calling Rust via C ABI and Makefile

Comment thread examples/cpp-calls-rust/Makefile
@TG199
TG199 requested a review from teor2345 March 26, 2026 01:50
@teor2345 teor2345 added the p-build-system Build system problems or examples label Mar 26, 2026
Comment thread examples/cpp-calls-rust/rust/src/lib.rs Outdated
// `no_mangle` is marked unsafe because it controls the symbol name at link time.
#[unsafe(no_mangle)]
pub extern "C" fn add(left: i32, right: i32) -> i32 {
left + right

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello I'm Ethan. One of the co-mentors with Outreachy. It looks like this successfully calls Rust from C++ which is great. It's often the case in interop that we need to both call Rust from C++ and call C++ from Rust. What would it take to extend this example so that our Rust code calls into C++?

@TG199 TG199 Mar 28, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @thunderseethe To support calling C++ from Rust, my understanding is that I would need to define a C++ function (exposed with C ABI) and then declare it in Rust using an extern block, calling it via unsafe.

I’m thinking of extending the current example with a small C++ function (e.g. multiply) and invoking it from the Rust code to demonstrate bidirectional interop.

Signed-off-by: Kelechi Ebiri <ebiritg@gmail.com>

@teor2345 teor2345 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's how to fix the CI failures

Comment thread examples/cpp-calls-rust/README.md
Comment thread examples/cpp-calls-rust/rust/src/lib.rs Outdated
fn multiply(a: i32, b: i32) -> i32;
}


Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of CI is failing because the formatting is slightly different to standard, try running cargo fmt --all

Comment thread examples/cpp-calls-rust/Makefile Outdated
all:
cd rust && cargo build --release

g++ cpp/main.cpp -Lrust/target/release -lrustlib -o main

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of CI is failing because of linker order. Most linkers expect all functions provided early on the command line, and the users of those functions listed later.

There's a circular dependency here, because:

  • main.cpp needs to be listed first so it can find add
  • but rustlib needs to be listed first so it can fund multiply

This can be fixed using library groups:
https://stackoverflow.com/questions/9380363/resolving-circular-dependencies-by-linking-the-same-library-twice

Signed-off-by: Kelechi Ebiri <ebiritg@gmail.com>
@TG199

TG199 commented Apr 1, 2026

Copy link
Copy Markdown
Contributor Author

Hi @teor2345 I've added --start-group/--end-group to the Makefile to handle the circular dependency for the full build. But CI jobs 1 and 2 also fail because they run cargo build and cargo test on the Rust crate alone, where multiply isn't available. Should I add a build.rs that compiles the C++ code so the Rust crate can build standalone, or is there a better way to structure this?

@teor2345

teor2345 commented Apr 1, 2026

Copy link
Copy Markdown
Collaborator

I've added --start-group/--end-group to the Makefile to handle the circular dependency for the full build. But CI jobs 1 and 2 also fail because they run cargo build and cargo test on the Rust crate alone, where multiply isn't available. Should I add a build.rs that compiles the C++ code so the Rust crate can build standalone, or is there a better way to structure this?

Huh, yeah, that is an issue.

For library builds, all the symbols don't need to be defined, so you're fine not having multiply.

For test builds, it's a binary, so it needs all the symbols. Your options are:

  • add a build.rs (possibly that only runs during tests), to build the C++ multiply
  • add a Rust version of multiply, that is #[cfg(test)], so it only builds during tests
  • replace the call to multiply during tests with the Rust * operation (using #[cfg(not(test))] for the current call)

I think the last option is the simplest, but I'm happy to guide you through whichever one you want.

@TG199

TG199 commented Apr 1, 2026

Copy link
Copy Markdown
Contributor Author

Ok, cool. I'd like to try the build.rs approach since it feels most relevant to the project's focus on build system integration. I'd appreciate guidance on that if you're willing!

TG199 added 2 commits April 2, 2026 23:16
Signed-off-by: Kelechi Ebiri <ebiritg@gmail.com>
Signed-off-by: Kelechi Ebiri <ebiritg@gmail.com>
@TG199
TG199 requested a review from teor2345 April 2, 2026 22:22

@teor2345 teor2345 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, this is a useful example of circular dependencies in code and tests.

@teor2345
teor2345 added this pull request to the merge queue Apr 6, 2026
Merged via the queue into rustfoundation:main with commit 934df7a Apr 6, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

p-build-system Build system problems or examples

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants