Post

Creating a DLL in Rust

How to create a DLL using Rust and execute the custom DLL function(s) using rundll32.

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).

1
cargo init --lib .

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).
1
cargo build --release

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"
1
Magic   010b   (PE32)
This post is licensed under CC BY 4.0 by the author.