title: Calling C++ DLL from C++ works, but not from C#
body: <p>I have a DLL called tccdvc.dll which is part of an SDK available here:</p>
  
  <p><a href="http://www.commell.com.tw/Download/Driver/Industrial%20Peripheral/Driver/MPX-885/MPX-885%20SDK%20(1.2)/SetupCOMMELL%20MPX-885_20100627.rar" rel="noreferrer">http://www.commell.com.tw/Download/Driver/Industrial%20Peripheral/Driver/MPX-885/MPX-885%20SDK%20(1.2)/SetupCOMMELL%20MPX-885_20100627.rar</a></p>
  
  <p>The DLL was written in C++ and examining the DLL shows it was linked with linker version 6.0, so I assume it was written with VC++ 6.0. The DLL does not come with source code, only a .lib file and a .h file. All exported functions are declared as extern "C" (so no C++ name mangling) and with APIENTRY (so __stdcall).</p>
  
  <p>I have written a C++ (not .NET) program in Visual Studio 2010 on Windows XP SP3 (32-bit) to access this tccdvc.dll. This works fine, both when using the provided .lib file and when using LoadLibrary/GetProcAddress. I have also written a C++ DLL (let's call it mywrapper.dll) that uses tccdvc.dll and, again, in two versions, one using the .lib file, the other using LoadLibrary/GetProcAddress. Again, this works fine. This mywrapper.dll uses the __cdecl calling convention. It contains a function called InitMyWrapperDLL() which loads the tccdvc.dll. The version of mywrapper.dll that uses LoadLibrary/GetProcAddress has code like this:</p>
  
  <pre><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");
    ...
  }
  </code></pre>
  
  <p>Again, using a C++ front-end, this works fine. However, when calling it from C# (on the same machine), the LoadLibrary("tccdvc.dll") call returns NULL. In C#, I am using:</p>
  
  <pre><code>[DllImport("mywrapper.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi, ExactSpelling=true, EntryPoint="InitMyWrapperDLL")]
  private static extern void InitMyWrapperDLL ();
  
  ...
  
  InitMyWrapperDLL();
  </code></pre>
  
  <p>When compiling mywrapper.dll using the provided tccdvc.lib file instead, it fails as well, with error code 0x8007045a (also known as 1114), meaning the DLL initialisation failed, and it gives mywrapper.dll as the name of the DLL. It turns out that the failure is because of tccdvc.dll, which gets loaded through mywrapper.dll.</p>
  
  <p>Using the following in C# fails as well:</p>
  
  <pre><code>[DllImport("tcc.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Ansi, ExactSpelling=true, EntryPoint="TCC_DVCOpen")]
  private static extern Int32 TCC_DVCOpen ();
  
  ...
  
  TCC_DVCOpen();
  </code></pre>
  
  <p>I have also used "unsafe" in the declaration, but that did not make any difference. Predictable, because LoadLibrary() fails, so it does not even get to TCC_DVCOpen().</p>
  
  <p>To pinpoint the problem, I used the LoadLibrary/GetProcAddress version of mywrapper.dll again and put the following code in my C# program:</p>
  
  <pre><code>[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();
  </code></pre>
  
  <p>After this, 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).</p>
  
  <p>I used Process Monitor by Sysinternals to get more information and I can see that tccdvc.dll is being read and mapped successfully. Nothing that Process Monitor displays gives me any hint as to why it fails when using C#, but not when using C++.</p>
  
  <p>Any ideas?
  Thanks!</p>