I have a DLL called tccdvc.dll, which is part of the SDK available here:
http://www.commell.com.tw/Download/Driver/Industrial%20Peripheral/Driver/MPX-885/MPX-885%20SDK%20(1.2)/SetupCOMMELL%20MPX-885_20100627.rar
The DLL was written in C ++, and examining the DLL shows that it was associated with the linker of version 6.0, so I assume that it was written using VC ++ 6.0. The DLL is not supplied with the source code, but only with the .lib file and the .h file. All exported functions are declared as extern "C" (so that no C ++ name smoothing) and with APIENTRY (so __stdcall).
I wrote a C ++ (non .NET) program in Visual Studio 2010 on Windows XP SP3 (32-bit) to access this tccdvc.dll. This works great both when using the provided .lib file and when using LoadLibrary / GetProcAddress. I also wrote a C ++ DLL (call mywrapper.dll) that uses tccdvc.dll and, again, in two versions, one using a .lib file, the other using LoadLibrary / GetProcAddress. Again, this works great. This mywrapper.dll uses the __cdecl calling convention. It contains the InitMyWrapperDLL () function, which loads tccdvc.dll. The version of mywrapper.dll using LoadLibrary / GetProcAddress has this code:
typedef int (APIENTRY *TCCPROCTYPE01)(); HMODULE TCCmodule; TCCPROCTYPE01 Proc_TCC_DVCOpen; extern "C" __declspec(dllexport) void InitMyWrapperDLL () { TCCmodule = LoadLibrary("tccdvc.dll"); Proc_TCC_DVCOpen = (TCCPROCTYPE01)GetProcAddress(TCCmodule, "TCC_DVCOpen"); ... }
Again, using the C ++ interface, this works great. However, when called from C # (on the same computer), a call to LoadLibrary ("tccdvc.dll") returns NULL. In C #, I use:
[DllImport("mywrapper.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi, ExactSpelling=true, EntryPoint="InitMyWrapperDLL")] private static extern void InitMyWrapperDLL (); ... InitMyWrapperDLL();
When compiling the mywrapper.dll file using the provided tccdvc.lib file, it also does not work with error code 0x8007045a (also known as 1114), which means that the DLL initialization failed, and it gives mywrapper.dll as the name of the DLL. It turns out that the failure is due to tccdvc.dll, which is loaded through mywrapper.dll.
Usage in C # also fails:
[DllImport("tcc.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Ansi, ExactSpelling=true, EntryPoint="TCC_DVCOpen")] private static extern Int32 TCC_DVCOpen (); ... TCC_DVCOpen();
I also used "unsafe" in the declaration, but that didn't make any difference. Predictably, because LoadLibrary () fails, so it doesn't even fall into TCC_DVCOpen ().
To determine the problem, I again used the version of mywrapper.dll LoadLibrary / GetProcAddress and put the following code in my C # program:
[DllImport("kernel32.dll")] private static extern IntPtr LoadLibrary (string lpLibFileName); [DllImport("kernel32.dll")] private static extern Int32 GetLastError (); ... IntPtr hdll1 = LoadLibrary("mywrapper.dll"); IntPtr hdll2 = LoadLibrary("tccdvc.dll"); Int32 errcode = GetLastError();
After that, hdll1 has a valid value, but hdll2 is 0. When using the .NET 3.5 Framework, GetLastError () returns 0x8007045a again, but when using .NET 4.0, GetLastError () returns 0 (ERROR_SUCCESS).
I used Sysinternals' Process Monitor to get more information, and I see that tccdvc.dll is being read and mapped successfully. Nothing that displays the process monitor gives me any hint as to why it doesn't work when using C #, but not when using C ++.
Any ideas? Thanks!