Use a C++ or other DLL with C# interop. We require the DllImport and dllexport keywords to get Windows interop working. We may have a C++ DLL dynamic link library that we need to hook up to a new C# GUI. We may have a custom legacy DLL we can't rewrite but have the ability to make modifications to.
Getting these things working can be a big challenge. First, we need to make or modify the DLL. In this article, I have the DLL set up with the following properties. In Visual Studio's Solution Explorer, you can right-click on the DLL project and look at the Property Pages to see these settings.
| This setting | Has this value |
| Configuration Type | Dynamic Library (.dll) |
| Use of MFC | Use Standard Windows Libraries |
| Use of ATL | Not Using ATL |
| Command Language Runtime Support | No Common Runtime Language Support |
| Whole Program Optimization | Use Link Time Code Generation |
For this article, we are not using the CLR in the C++ DLL. This is a very important point to consider because if you use CLR, you will have managed C++ code and you can use better interfaces between C++ and C#. Also, in the Linker property page, you can set the output name of the DLL, such as the name CoreDLL.dll, which I use in this article.
The DLL and the C# EXE need to communicate. You do this by defining extern "C" functions in your C++ DLL. There is a special syntax for doing this that you must use. The next block of code shows an extern function you put in your DLL.
// This code should be put in a header file for your C++ DLL. It declares
// an extern C function that receives two parameters and is called SimulateGameDLL.
// I suggest putting it at the top of a header file.
extern "C" {
__declspec(dllexport) void __cdecl SimulateGameDLL (int a, int b);
}
In the above example, the __declspec(dllexport) part is standard and not required to be referenced elsewhere. Our C# GUI will need to call this function from an UnsafeNativeMethods class. Let's look at the extern function above in the same header file in the C++ DLL.
// The keywords and parameter types must match the above extern
// declaration.
extern void __cdecl SimulateGameDLL (int num_games, int rand_in) {
// This is part of the DLL, so we can call any function we want
// in the C++. The parameters can have any names we want to give
// them and they don't need to match the extern declaration.
}
First compile your DLL and make sure it is in the same directory as the C# Windows Forms GUI. Let's look at the code we need to write in the C# interop code. The following code needs to be added to a class in C# in your Windows Forms program.
/// <summary>
/// A C-Sharp interface to the DLL, written in C++.
/// </summary>
static class GameSharp
{
/// <summary>
/// The native methods in the DLL's unmanaged code.
/// </summary>
internal static class UnsafeNativeMethods
{
const string _dllLocation = "CoreDLL.dll";
[DllImport(_dllLocation)]
public static extern void SimulateGameDLL(int a, int b);
}
}
We use the static UnsafeNativeMethods class to house the extern declaration in C#. The function name is the same as the one in the C++ DLL. We can use a const string to designate the filename of the DLL. The DllImport("name.dll") must have the name of the C++ you are building.
Look at the class GameSharp that I showed in the previous example. We need to add another static method to that class so that the rest of the C# program can use the native method. This is essentially a proxy method that forwards the method call.
static class GameSharp
{
// [code omitted, see above example]
/// <summary>
/// Simulate N games in the DLL.
/// </summary>
/// <param name="num">The number of games to simulate.</param>
public static void SimulateGameCall(int num)
{
UnsafeNativeMethods.SimulateGameDLL(num, new Random().Next());
}
}
There are many problems that can happen, and most of them probably will. The words "problem" and "probably" share a prefix, after all. Next in this document I want to list some gotchas and hint at some more problems I want to solve on this site.
Use the dllexport and DllImport keywords listed here for one way to make an old C++ DLL work with a C# GUI. This is not a comprehensive guide to C++ interop with C#, but it contains material that can help you get started. The approach here is not always optimal, but it works well for me and I understand it.