In this post we’ll look at how to create a DLL using Rust that contains a custom function, then executing that function using rundll32.
Create a new Rust Project
To start we’ll create a new folder and initialize it with --lib to create a package with a library target (src/lib.rs).
Next we’ll add the crate-type field in the [lib] section of cargo.toml.
1
2
3
4
5
6
7
8
9
| [package]
name = "dll_test"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib"]
[dependencies]
|
cdylib means a dynamic system library will be produced. This is used when compiling a dynamic library to be loaded from another language.- This output type will create
*.so files on Linux, *.dylib files on macOS, and *.dll files on Windows.
Rust Code
Next we’ll create a new function MyTestFunction that we want to be able to call.
1
2
3
4
5
6
7
| #[unsafe(no_mangle)]
pub fn MyTestFunction() {
let file_name = "C:\\Temp\\Rust DLL output file.txt";
let data = "Test file written using my Rust DLL";
let _ = std::fs::write(file_name, data);
}
|
unsafe is required for no_mangle in newer versions of Rust (2024 edition I believe).
In the target/release folder we can see our compiled DLL dll_test.dll.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| Directory of C:\Rust\dll_test\target\release
28/04/2026 07:28 AM <DIR> .
28/04/2026 07:28 AM <DIR> ..
28/04/2026 07:28 AM 0 .cargo-lock
28/04/2026 07:28 AM <DIR> .fingerprint
28/04/2026 07:28 AM <DIR> build
28/04/2026 07:28 AM <DIR> deps
28/04/2026 07:28 AM 126 dll_test.d
28/04/2026 07:28 AM 129,024 dll_test.dll
28/04/2026 07:28 AM 883 dll_test.dll.exp
28/04/2026 07:28 AM 1,744 dll_test.dll.lib
28/04/2026 07:28 AM 1,200,128 dll_test.pdb
28/04/2026 07:28 AM <DIR> examples
28/04/2026 07:28 AM <DIR> incremental
6 File(s) 1,331,905 bytes
7 Dir(s) 1,637,719,965,696 bytes free
|
Execute Function using rundll32
We’ll copy dll_test.dll to C:\Temp then execute our custom function using rundll32.
1
| C:\Temp>rundll32 dll_test.dll,MyTestFunction
|
Checking the current directory we can see the file our DLL function made.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| C:\Temp>dir
Volume in drive C has no label.
Volume Serial Number is XXXX-XXXX
Directory of C:\Temp
28/04/2026 07:34 AM <DIR> .
28/04/2026 07:34 AM <DIR> ..
28/04/2026 07:34 AM 133,120 dll_test.dll
28/04/2026 07:34 AM 35 Rust DLL output file.txt
2 File(s) 133,155 bytes
2 Dir(s) 1,640,106,426,368 bytes free
C:\Temp>type "Rust DLL output file.txt"
Test file written using my Rust DLL
|
Function Declaration Notes
From other sources I’ve seen you might need to use the one of the below function definitions if you are having issues with crashes due to unexpected parameters.
- I didn’t have any issues when using
pub fn MyTestFunction, but I only tested the DLL using rundll32, so other applications might not be as forgiving.
1
2
3
| pub extern "C" fn MyTestFunction()
pub extern "system" fn MyTestFunction()
pub extern "system" fn MyTestFunction(_hwnd: *mut std::ffi::c_void, _hinst: *mut std::ffi::c_void, _lp_cmd_line: *mut u8, _n_cmd_show: i32)
|
Building for 32-bit
Add the 32-bit Windows target for rust.
1
| rustup target add i686-pc-windows-msvc
|
Build a 32-bit binary.
1
| cargo build --release --target i686-pc-windows-msvc
|
Confirm 32-bit Build
1
| objdump -x dll_test.dll | grep "Magic"
|