Alex
Alex

Reputation: 278

C#/C++ Callback Passed as NULL

I am having some trouble passing a callback function from C# to a C++ unmanaged DLL. When running the program theDLL receives NULL instead of the callback.

The callback function is defined as

typedef void(__cdecl *CallbackFunction)();

The C++ functions is defined as

__declspec(dllexport) void __cdecl StreamData(unsigned char *Buffer, unsigned int BufferSize, unsigned long Points,
 unsigned short AveragingPower, CallbackFunction BufferUpdated);

The C# callback and function delegates are defined as

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void BufferUpdatedCallback();

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void StreamDataDelegate(byte[] Buffer, uint BufferSize, ulong Points,
 ushort AveragingPower, BufferUpdatedCallback BufferUpdated);

The C++ function definitly works correctly as I have tested it from a C++ Console application and it works correctly. In C# I can acquire a pointer for the delegate of the callback via Marshal.GetFunctionPointer(Delegate d) however when I step through the program at the point it enters the StreamData function the pointer becomes NULL inside the DLL. The calling conventions are consistent across the DLL and the C# delegates.

Am I missing something quite basic? And does anybody know of a way of correcting the problem?

UPDATE

If the unsigned long Points parameter is removed from both the DLL and C# then the function works correctly, otherwise the callback is NULL.

Upvotes: 0

Views: 1555

Answers (2)

Hans Passant
Hans Passant

Reputation: 942257

An unsigned long in the C++ compiler is a 32-bit integer type. You however declared as ulong, a 64-bit type. The argument misalignment this causes makes the delegate look like NULL in the C++ code, it is reading the upper 32-bits of that ulong variable.

You must use uint in your [DllImport] declaration for the Points argument.

Upvotes: 4

Resource
Resource

Reputation: 544

Try this:

private delegate void StreamDataDelegate(ref byte[] Buffer, uint BufferSize, ulong Points, ushort AveragingPower, BufferUpdatedCallback BufferUpdated);

Upvotes: 0

Related Questions