Wednesday, September 17, 2008

.NET Compact Framework unmanaged callbacks: bool not invited

The .NET Compact Framework 2.0 is supposed to support unmanaged callbacks: you pass a delegate into C/C++ code via P/Invoke and the Framework converts it to a thunk. It passes the thunk to C/C++, and when the C/C++ code calls the thunk, the thunk calls your delegate.

Previously I had success passing strings:
// C# declaration
public delegate void ExceptionArgumentDelegate([MarshalAs(UnmanagedType.LPWStr)]
string message, [MarshalAs(UnmanagedType.LPWStr)] string paramName);
// C++ declaration
typedef void (__stdcall* ExceptionArgumentCallback_t)
(const wchar_t *, const wchar_t *);
void SetCallback(ExceptionArgumentCallback_t callback);
// P/Invoke declaration
[DllImport("DllNameHere", EntryPoint="SetCallback")]
public static extern void SetCallback(ExceptionArgumentDelegate callback);

But I couldn't pass the following delegate type:
// C# declaration
public delegate bool ProgressCallback([MarshalAs(UnmanagedType.LPWStr)]
string message, int itemsProcessed, int totalItems);
// C++ declaration
typedef bool (__stdcall *ProgressCallback)(PCTSTR, int, int);

I get a NotSupportedException with the rather vague error message "0x80131515". Thanks Microsoft! Well, it turns out that a callback is not allowed to have a bool return type. The solution: change the return type on the C# side to int, then return 0 instead of false and 1 instead of true. Just to be on the safe side, you might want to change the C++ side to return int also. But that wasn't needed in my case (XScale PXA processor).

Interestingly, my cursory examination suggests you are allowed to pass bool as an argument, and even ref bool works (ref bool corresponds to bool* on the C++ side).


Post a Comment

<< Home