Abomination is a Visual Studio solution template designed to seamlessly integrate Rust library development into code that can be called from C/C++ on Windows. It sets up a workflow where you write core logic in Rust, expose it via C-style function prototypes, and then consume it in a C++ application. This template supports building 32-bit and 64-bit executables from a 64-bit Windows development environment.
This template is structured into three main parts:
-
Abomination.cpp
This is the primary C++ source file containing themain()
function. It invokes functions implemented in Rust by including and calling prototypes declared inRust.h
. -
Rust.h
This header file declares the C-compatible function prototypes for Rust functions. These functions are defined and exported from the Rust library and then called fromAbomination.cpp
. -
Mutations (Rust Cargo Project)
TheMutations
directory is a standalone Rust Cargo project that compiles into a static library.- lib.rs: This file contains the core Rust code and the
#[no_mangle]
exported functions. By default, a few example functions and unit tests are provided. - Any additional
.rs
source files must be manually added to theMutations/src
directory (or another directory structure as you prefer) and then referenced inlib.rs
or via Rustmod
declarations.
- lib.rs: This file contains the core Rust code and the
-
Develop in Rust:
Implement your core functionality in Rust within theMutations
project. Begin by editinglib.rs
and adding new functions that will be exposed to C++. For each new Rust function you plan to call from C++, ensure it has the#[no_mangle]
andextern "C"
attributes, and is compiled with apub
visibility.Example:
#[no_mangle] pub extern "C" fn add_numbers(a: u64, b: u64) -> u64 { a + b }
-
Declare in C (Rust.h):
After creating (or updating) a function in Rust, add a corresponding C-style function prototype inRust.h
.Example:
#pragma once /* Rust.h * C-style prototype declerations of the functions implemented in lib.rs */ extern "C" unsigned long long add_numbers(unsigned long long a, unsigned long long b); extern "C" unsigned long long mult_numbers (unsigned long long a, unsigned long long b);
-
Call From C++ (Abomination.cpp):
With the function declared inRust.h
, you can now safely call it fromAbomination.cpp
.Example:
#include <iostream> #include "Rust.h" int main() { constexpr unsigned long long a = 2; constexpr unsigned long long b = 3; unsigned long long c = add_numbers(a, b); std::cout << "Hello World!\n"; std::cout << "Output of add:" << c << "\n"; std::cout << "Output of mult:" << mult_numbers(a, b) << "\n"; }
-
Build and Run:
- Set the active configuration to your desired build mode (e.g.,
Debug
orRelease
). - Build the solution in Visual Studio. The Rust library will be compiled into a static library, and
Abomination.cpp
will link against it. - Run the executable from within Visual Studio or directly from the build output directory.
- Set the active configuration to your desired build mode (e.g.,
-
Add More Rust Source Files:
If you need more complex Rust modules, add.rs
files underMutations/src
(or a structured layout of your choosing), and reference them fromlib.rs
using Rust’s module system:// In lib.rs mod my_module; // references my_module.rs in src/
Rebuild the solution after adjusting your code and prototypes as needed.
This template includes a "Test Rust" configuration. Running it will:
- Invoke
cargo test
within theMutations
project directory. - Execute the Rust-based unit tests defined in
lib.rs
(and any other modules).
How to run Rust tests:
- Switch to the
Test Rust
configuration in Visual Studio. - Clean the solution via
Build -> Clean Solution
- Build and run to execute the Rust unit tests directly from within the IDE’s output window.
You must clean the solution in-between running consecutive rounds of unit testing.
When you finish testing, switch back to a standard C++ configuration (like Debug
or Release
) to continue normal development.
- Windows (x86_64) with Visual Studio installed.
- Rust toolchain (with
cargo
) installed and accessible in your system PATH.
Install Rust
- The template assumes the Rust static library name and paths are consistent with
Mutations
project settings. - Make sure to keep your
#[no_mangle]
andextern "C"
attributes aligned with any functions you want to expose. The function signature in Rust must match the C prototype inRust.h
. - Adjust compiler flags, optimization levels, or calling conventions as needed in both the Rust Cargo settings (
Cargo.toml
) and the Visual Studio project properties. - The current template does not support directly debugging Rust code from Visual Studio.
If you encounter issues integrating Rust and C/C++ code, consider the following resources:
Please feel free to submit pull requests for improvements.