Calling C ++ DLL from C ++ works, but not from C #

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!

+8
c ++ c # dll
source share
2 answers

I have some tips for you:

  • You can create a C ++ / CLI class library project, and then reference it in your C # project.
  • In my case, I found out that UnmanagedFunctionPointerAttribute is important for the call,
  • There was a case, no matter what I did, the call to .LLL never worked with C #, only .LIB worked for me (which means the implementation of my first sentence). The troubleshooting led me to the fact that the "dll space" is not suitable for this particular library.

(Regarding the last sentence: I am by no means an expert on C ++, in fact this is the only project I have done so far. It certainly deserves more detailed information, but I never knew and did not know, to find the source of the problem, but this is because I just needed it. Thanks for pointing out any bug / better explanation.)

Here are some of the solutions that apply to my problem:

How to use C callback from C #? There is a link to .DLL if you want all my code to just ask.

In addition, a few tools that were useful to me in this domain:

May the force be with you :-)

+1
source share

So, your C-code works when called from a C ++ application, but identical code crashes when called from the .NET binary, where it does not work in LoadLibrary ...

This is just a hunch, so I'm not sure what describes your circumstances, but LoadLibrary has some complex criteria for resolving relative DLL paths, which may vary depending on certain parameters. I do not know them all from the head. Maybe something in the manifest of the .exe binary binary prevents it from finding the DLL according to these rules. You can try changing the PATH environment variable or loading the DLL with an absolute path. (You can use GetModuleFileName etc. to find the absolute path of your own code ...)

0
source share

All Articles