C# using PInvoke to call an unmanaged DLL

Recently I've found myself having to do some pinvoking with .net. Microsoft offers an excellent primer on the subject.

http://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx

For it's many great benefits the .net framework doesn't do everything. You will find yourself having to invoke a win32 API function call at some point in your career.


I'm going to offer some quick and dirty samples on getting data back and forth using the platform invoke. First you cannot invoke any classes using pinvoke. You get 1 function call at a time. If you want classes you will need to write a custom CLI/C++ wrapper. But that goes beyond the scope of this post.

First let's look at the unmanaged\win32 side of things. Let's say you have a dll called MyDll.dll. In this dll you have a bunch of functions.

// this lets use export functions from the dll
#define  DllExport  __declspec( dllexport ) 

// first we use extern "C" so we don't get name mangling in the dll
// .net doesn't play well with C++ function names so we must use the extern
extern "C"
{    
    // we're going to export this function using the __stdcall calling convention
    // .net uses __stdcall by default, so we want to ensure we have it here
    DllExport int __stdcall Add( int A, int B )
    {
        return A + B;
    }
}


So a quick re-cap, we're going to export a single function called Add, using the __stdcall calling convention. Now let's look at using this function in a .net application. The trick is to use the DllImport attribute, located in the System.Runtime.InteropServices namespace. Below is an example of using the DllImport to use our Add method.

[DllImport( "MyDll.dll" )]
public static extern int Add( int A, int B );

// call our add method!
int result = Add( 1, 2 );


.Net is actually very good at matching the basic data types (int, long, bool, etc). Strings, delegates, classes, structs, etc require more work to function correctly. For those we will start getting into more manual marshaling of data. I have found for most basic dll calls letting the framework handle the marshaling saves a lot of time.

Comments

Popular Posts