Dot Net Perls
C#

DllImport and dllexport Interop

by Sam Allen

Problem

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.

Solution

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

Note on CLR

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.

dllexport in C++

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

DllImport in C#

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.

Call C++ Methods

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());
    }
}

Considerations and gotchas

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.

Discussion

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.

© 2008 Sam Allen. All rights reserved.

Ads by The Lounge