Вызов C++ DLL из C++ работает, но не из C#

У меня есть DLL с именем tccdvc.dll, которая является частью SDK, доступного здесь:

http://www.commell.com.tw/Download/Driver/Industrial%20Peripheral/Driver/MPX-885/MPX-885%20SDK%20(1.2 )/SetupCOMMELL%20MPX -885 _20100627.rar

DLL была написана на C++, и изучение DLL показывает, что она была связана с компоновщиком версии 6.0, поэтому я предполагаю, что она была написана с помощью VC++ 6.0. DLL не поставляется с исходным кодом, только файл.lib и файл.h. Все экспортируемые функции объявлены как extern "C" (, поэтому нет искажения имени C++ )и с APIENTRY (, поэтому __stdcall ).

Я написал программу C++ (, а не.NET )в Visual Studio 2010 на Windows XP SP3 (32 -бит )для доступа к этой tccdvc.dll. Это прекрасно работает как при использовании предоставленного файла.lib, так и при использовании LoadLibrary/GetProcAddress. Я также написал C++ DLL (, назовем ее mywrapper.dll ), которая использует tccdvc.dll и, опять же, в двух версиях, одна использует файл.lib, другая использует LoadLibrary/GetProcAddress. Опять же, это работает нормально.Эта библиотека mywrapper.dll использует соглашение о вызовах __cdecl. Он содержит функцию InitMyWrapperDLL (), которая загружает tccdvc.dll. Версия mywrapper.dll, использующая LoadLibrary/GetProcAddress, имеет такой код:

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();

При компиляции mywrapper.dll с использованием предоставленного файла tccdvc.lib также происходит сбой с кодом ошибки 0x8007045a (, также известным как 1114 ), что означает сбой инициализации DLL, и он дает mywrapper.dll в качестве имени DLL. Оказывается, сбой происходит из-за tccdvc.dll, который загружается через mywrapper.dll.

Использование следующего в C #также не работает:

[DllImport("tcc.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Ansi, ExactSpelling=true, EntryPoint="TCC_DVCOpen")]
private static extern Int32 TCC_DVCOpen ();

...

TCC_DVCOpen();

Я также использовал «небезопасно» в объявлении, но это не имело никакого значения. Предсказуемо, потому что LoadLibrary()дает сбой, поэтому даже не доходит до TCC_DVCOpen().

Чтобы точно определить проблему, я снова использовал версию mywrapper.dll LoadLibrary/GetProcAddress и поместил следующий код в свою программу 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 Framework GetLastError ()снова возвращает 0x8007045a, но при использовании.NET 4.0 GetLastError ()возвращает 0 (ОШИБКА _УСПЕХ ).

Я использовал Process Monitor от Sysinternals, чтобы получить больше информации, и я вижу, что tccdvc.dll успешно читается и сопоставляется. Ничто из того, что отображает Process Monitor, не дает мне никакого намека на то, почему он терпит неудачу при использовании C #, но не при использовании C++.

Любые идеи? Спасибо!

8
задан zarulad 5 July 2012 в 13:48
поделиться