Lets completely work through a Platform Invoke Example.
For simplicity I’ll use a Windows Mobile Emulator, but it would simply apply to an actual Windows Mobile Device/Windows CE device.
textBox1.Text = DateTime.Now.ToString();
OK So we have connectivity and can create, build and run an application.
Next we add a class which will encapsulate the native code in the C# application.
using System; using System.Runtime.InteropServices; namespace PInvoke { internal static class Native { } }
using System; using System.Runtime.InteropServices;
namespace PInvoke { internal static class Native {
} }
NATIVE_API int fnNative(void); NATIVE_API int fnNative2(int num);
NATIVE_API int fnNative(void);
NATIVE_API int fnNative2(int num);
NATIVE_API int fnNative(void) { return 42; }
NATIVE_API int fnNative2(int num) { return num*2; }
const string DLLFile = "Native.dll"; //NATIVE_API int fnNative(void); //NATIVE_API int fnNative2(int num); [DllImport(DLLFile)] public static extern int fnNative(); [DllImport(DLLFile)] public static extern int fnNative2(int num);
const string DLLFile = "Native.dll";
//NATIVE_API int fnNative(void);
//NATIVE_API int fnNative2(int num);
[DllImport(DLLFile)] public static extern int fnNative();
[DllImport(DLLFile)] public static extern int fnNative2(int num);
private void button1_Click(object sender, EventArgs e) { textBox1.Text = DateTime.Now.ToString(); } private void Native42_Click(object sender, EventArgs e) { //Should get 42 in textbox int num = PInvoke.Native.fnNative(); textBox1.Text = num.ToString(); } private void NativeDouble_Click(object sender, EventArgs e) { //Convert the number in the textbox into a number and then double it try { int num = int.Parse(textBox1.Text); num = PInvoke.Native.fnNative2(num); textBox1.Text = num.ToString(); } catch { textBox1.Text = "Enter a number (only) here"; } }
private void button1_Click(object sender, EventArgs e) { textBox1.Text = DateTime.Now.ToString(); }
private void Native42_Click(object sender, EventArgs e) { //Should get 42 in textbox int num = PInvoke.Native.fnNative(); textBox1.Text = num.ToString(); }
private void NativeDouble_Click(object sender, EventArgs e) { //Convert the number in the textbox into a number and then double it try { int num = int.Parse(textBox1.Text); num = PInvoke.Native.fnNative2(num); textBox1.Text = num.ToString(); } catch { textBox1.Text = "Enter a number (only) here"; } }
IT WON’T WORK .. We have one more thing to do:
C++ compiler mangles names (the function names). We have just specified the functions in the C# code by the same names as in the C++ source. We could use ordinals to get to them instead. Its easier to tell the compiler not to mangle the names with an extern “C” directive. (There are heaps of articles on the web on C++ name mangling).
extern "C" NATIVE_API int fnNative(void); extern "C" NATIVE_API int fnNative2(int num);
extern "C" NATIVE_API int fnNative2(int num);
We can create a native DLL that can be called from managed code. We could potentially use this to call hardware in Windows CE. But hardware calls often require callbacks. That’s next.