I’ve written a DLL in unmanaged visual C++, and I’m having a little trouble getting it to work with both C# and C++ applications. Here’s what the prototype in the C++ DLL looks like:
extern "C" __declspec(dllexport) int WINAPI ZBNConnect( UCHAR dev, LPARAM hWnd, ZBCallbackFn rfn, ZBCallbackFn nfn, int DevType, byte * DevAddr, ZBCallbackFn dfn );
My C# application can link to the function, no problem, but when it tries to call the function an exception is thrown:
catch (Exception e) { /* ... */ }
e.Message = “Object reference not set to an instance of an object.”
Oddly, if I take WINAPI out of the prototype in the DLL, and recompile, the C# application calls the function without any problems. Unfortunately, the WINAPI must remain because that is how the function is defined in the C++ application.
The function is currently prototyped in the C# application like this:
public delegate int ZBNConnectDelegate(uint dev, IntPtr hWnd, USBCallbackDelegate rfn, NotifyCallbackDelegate nfn, uint DevType, byte[] DevAddr, ZBdebugCallbackDelegate dfn);
public ZBNConnectDelegate ZBNConnect;
procName = "ZBNConnect";
fUintPtr = Kernel32.GetProcAddress(dllHandle, procName);
if (fUintPtr == UIntPtr.Zero)
{
throw new ArgumentException(procName);
}
fIntPtr = unchecked((IntPtr)(long)(ulong)fUintPtr);
ZBNConnect = (ZBNConnectDelegate)Marshal.GetDelegateForFunctionPointer(fIntPtr, typeof(ZBNConnectDelegate));
How can I modify the C# application to get this working? Thanks.
EDIT: Additional Information
A static link ([DllImport...]) is not an option because depending on which hardware is attached to the system a different DLL that supports the attached hardware is loaded at run-time. Both DLLs have the same API calls.
It turned out that adding
WINAPIto the function declaration and definition was causing the function name in the DLL to be mangled. Unfortunately,WINAPIwas required to maintain compatibility with applications already deployed. The fix was to add an extra export to the linker: