When you program in Rust, especially in a non-trivial project, there is a good chance that you will need to call “external” functions (usually, C/C++) that are available in a DLL (we are talking about the Windows platform here). It could be because you wish to re-use some code that you have earlier written in C/C++, or you might be calling a 3rd party library that provides some functionality you need at this point. OK, how easy is this process?
As it turns out, this is not difficult at all. In this article, I will show the steps to get this integration working.
First, my development environment:
1) Visual Studio Professional 2022 (64 bit) 17.1.0 on Windows 10.
2) Rust 1.59.0 running on Windows 10 (64 bit)
3) CLion 2021.3.4 IDE with Rust Plugin
Building the DLL and LIB
Although I could have assumed that we already have the DLL and corresponding LIB, let me show you how to create a simple DLL from scratch using Visual Studio 2022.
1) Launch VS 2022. Select the option to “Create a New Project” and choose the type as “DLL”. Click “Next”.
2) Then specify the Project Name and Location and click “Create”:
3) This will result in the auto generation of project files, including a bare-bones “dllmain.cpp” file:
Let us delete the generated function and type in our function, which will be called from Rust:
The extra qualifiers before the function reurn type ensure that this will be exported from the DLL without any name mangling.
4) Make sure the target is “x64”. Additionally, for our example, we will choose “Release” mode.
5) Build the project. This will result in the files “DllExample.dll” and “DllExample.lib” being created in “x64\Release” sub-directory within the project directory.
We need the above two files when we build our Rust project in CLion.
Rust Example that Uses the DLL
We now launch CLion and create a New Rust project. Here is the actual Rust code we will be using:
Since we are making a call to an external function, we have to declare the equivalent function signature in Rust, and also specify the external library to use. Notice that we are indicating the “kind” as “static” since we will be linking the Rust code with our DllExample.lib
Another important thing to note in the above code is the use of “unsafe” block. This is required since an external (non-Rust) code might have “unsafe” behavior.
Before we build the Rust project, we need to copy our DllExample.lib file to a location that can be configured in the “LIB” path. This is what I did:
a) Copied the LIB file to the Rust project directory. Here are the files in this directory:
Then I updated the “LIB” environment variable to include the path: “F:\Rust Projects\CallingDLL\”
b) Copied the DllExample.dll file to the “debug” subdirectory under “target” directory:
This is required in order to run the final Executable file.
We can now build and run the Rust project.
Here is the program output as it appears within CLion IDE:
This shows that our external function in the DLL is called from within Rust. You can download the relevant files from here.
That was straightforward, right? You may find this article useful if you would like to explore “Foreign Function Interface (FFI)” of Rust in greater detail.
Have a nice week!
Where exactly do you set the LIB path environment variable?