Implementing interoperability, reflection, and mailing functionality in a .NET Framework application
- Call unmanaged DLL functions within a .NET Framework application, and control the marshalling of data in a .NET Framework application.
- Create a class to hold DLL functions;
- Create prototypes in managed code
- Call a DLL function
- Call a DLL function in special cases, such as passing structures and implementing callback functions
Rather than declare the array in managed space and marshal it over, it proved far easier to allocate and fill the array in the unmanaged space. The example below shows how to call the native ColorChooser dialog. The color chooser dialog requires a specific structure to be populated before it is called.
Calling unmanaged code from C# Example
using System;
using System.Runtime.InteropServices;
namespace InteropExample
{
public class Win32
{
[DllImport("comdlg32.dll")]
public static extern bool ChooseColor(CHOOSECOLOR pChooseColor);
[DllImport("Kernel32.dll")]
public static extern IntPtr LocalAlloc(int flags, int size);
[DllImport("Kernel32.dll")]
public static extern int LocalFree(IntPtr addr);
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public class CHOOSECOLOR:IDisposable
{
public Int32 lStructSize;
public IntPtr hwndOwner;
public IntPtr hInstance;
public Int32 rgbResult;
public IntPtr lpCustColors;
public uint Flags;
public Int32 lCustData = 0;
public IntPtr lpfnHook;
public IntPtr lpTemplateName;
public CHOOSECOLOR()
{
lStructSize = System.Runtime.InteropServices.Marshal.SizeOf(this);
hwndOwner = IntPtr.Zero;
hInstance = IntPtr.Zero;
rgbResult = 0; //black
lpCustColors = Win32.LocalAlloc(64, 64);
//Fill up some random custom colors, just to show we can write to unmanaged memory
for(int i = 0; i <16; i++)
{
System.Runtime.InteropServices.Marshal.WriteInt32((IntPtr)(lpCustColors), sizeof(UInt32) * i, 0x0004937E << i);
}
Flags = 0;
lCustData = 0;
lpfnHook = IntPtr.Zero;
lpTemplateName = IntPtr.Zero;
}
public virtual void Dispose()
{
Win32.LocalFree(lpCustColors);
}
}
class Program
{
static void Main(string[] args)
{
CHOOSECOLOR chooseColorData = new CHOOSECOLOR();
Win32.ChooseColor(chooseColorData);
}
}
}
Results
Additional Resources
.NET Platform Invoke Examples (Microsoft)
Win32 ChooseColor Function (Microsoft)
Win32 Type Mapping between C++ and C# (Code Project)