我有一个名为tccdvc.dll的DLL,它是可在此处获得的SDK的一部分:
该DLL是用C++编写的,检查该DLL时发现它与链接器版本6.0链接,因此我认为它是使用VC++ 6.0编写的。该DLL没有附带源代码,只有一个.lib文件和一个.h文件。所有导出函数都声明为extern "C"(因此没有C++名称修饰)并且使用APIENTRY(因此是__stdcall)。
我已经在Windows XP SP3(32位)上使用Visual Studio 2010编写了一个C++程序(不是.NET程序),以访问这个tccdvc.dll。这工作正常,无论是使用提供的.lib文件还是使用LoadLibrary / GetProcAddress。我还编写了一个C++ DLL(称其为mywrapper.dll),它使用tccdvc.dll,在两个版本中运行良好,一个版本使用.lib文件,另一个版本使用LoadLibrary / GetProcAddress。同样,这也很好用。此mywrapper.dll使用__cdecl调用约定。它包含一个名为InitMyWrapperDLL()的函数,该函数负责加载tccdvc.dll。使用LoadLibrary / GetProcAddress的mywrapper.dll版本的代码如下:
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");
...
}
再次使用C++前端,这个功能很好。但是,从C#调用它时(在同一台机器上),LoadLibrary(“tccdvc.dll”)调用返回NULL。在C#中,我正在使用:
[DllImport("mywrapper.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi, ExactSpelling=true, EntryPoint="InitMyWrapperDLL")]
private static extern void InitMyWrapperDLL ();
...
InitMyWrapperDLL();
当使用提供的tccdvc.lib文件编译mywrapper.dll时,它也会失败,并显示错误代码0x8007045a(也称为1114),表示DLL初始化失败,并将mywrapper.dll作为DLL名称。结果发现,故障是由于通过mywrapper.dll加载的tccdvc.dll引起的。
在C#中使用以下内容也会失败:
[DllImport("tcc.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Ansi, ExactSpelling=true, EntryPoint="TCC_DVCOpen")]
private static extern Int32 TCC_DVCOpen ();
...
TCC_DVCOpen();
我还在声明中使用了“unsafe”,但是这没有任何区别。这是可以预料的,因为LoadLibrary()失败,所以甚至无法到达TCC_DVCOpen()。
为了确定问题,我再次使用了LoadLibrary/GetProcAddress版本的mywrapper.dll,并将以下代码放入我的C#程序中:
[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();
在此之后,hdll1具有有效值,但hdll2为0。使用.NET 3.5框架时,GetLastError()再次返回0x8007045a,但是在使用.NET 4.0时,GetLastError()返回0(ERROR_SUCCESS)。
我使用Sysinternals的Process Monitor获取更多信息,可以看到tccdvc.dll被成功读取和映射。 Process Monitor显示的任何内容都没有给出原因,说明为什么在使用C#时失败,而在使用C ++时不会失败。
有什么想法吗? 谢谢!
tccdvc.dll
是否会产生任何额外的线程? - qehgt