Delphi Loadlibrary возвращает 0 (LastErrorcde = 3221225616) Что это значит? - PullRequest
4 голосов
/ 21 августа 2010

Мне нужно использовать стороннюю DLL в нашем основном приложении.Когда я статически связываюсь с предоставленной DLL, она работает нормально, и я могу экспортировать функции DLL.Но мы не хотим, чтобы наше основное приложение зависело от этой dll при запуске, поэтому я попытался динамически загрузить DLL, когда мне это нужно:

DLLHandle := LoadLibrary('3rdparty.dll');
ret := GetLastError();
if DLLHandle = 0 then
begin
  err := SysErrorMessage(ret);
  Writeln(err);
end //...

, но не сработало: функция LoadLibrary возвращает 0, а код LastErrorcode3221225616. Поскольку я не знаю, что я делаю неправильно, я попробовал то же самое (на том же компьютере), закодированный в c, и это работает: но что не работает с delphi?: Я вызываю ту же функцию LoadLibrary на той же DLL!

Когда я наблюдаю с помощью ProcMon, я вижу, что загружается 3-я DLL-часть 3-й стороны, а также загружаются зависимые DLL 3-й DLL-библиотеки.Таким образом, Windows, безусловно, находит DLL.Но где-то в процессе загрузки происходит сбой: когда я пытаюсь загрузить DLL с помощью LoadLibraryEX с помощью DONT_RESOLVE_DLL_REFERENCES или LOAD_LIBRARY_AS_DATAFILE, это также работает (но я не могу, конечно, вызвать необходимые функции ...)

Я ухожуидей: надеюсь, вы, ребята, можете помочь мне в дальнейшем ...

THX в Adv.Кристоф

Ответы [ 5 ]

10 голосов
/ 21 августа 2010

Работает ли это?

var
  SavedCW: word;

...

SavedCW := Get8087CW;
Set8087CW(SavedCW or $7);
DLLHandle := LoadLibrary('3rdparty.dll');
Set8087CW(SavedCW);
if DLLHandle = 0 then
begin
  ret := GetLastError();  
  err := SysErrorMessage(ret);
  Writeln(err);
end //...

Некоторое обсуждение:

Код ошибки 3221225616, кажется, при запросе Google является результатом недопустимой операции с плавающей запятой.Теперь это кажется очень техническим;действительно, какое отношение имеет загрузка библиотеки к вычислениям с плавающей запятой?Слово управления с плавающей запятой (CW) является битовым полем, где биты определяют, как процессор должен обрабатывать ошибки с плавающей запятой;на самом деле довольно распространено, что непредвиденные ошибки с плавающей запятой можно устранить, изменив один из этих битов на 1 (что, кстати, является состоянием по умолчанию).Для другого примера см. мой вопрос , в котором я получаю совершенно неожиданную ошибку деления на ноль, которая решается установкой бита «деления на ноль» управляющего слова равным 1.

6 голосов
/ 21 августа 2010

Возможно связано: http://discuss.joelonsoftware.com/default.asp?joel.3.88583.15

Попробуйте использовать SafeLoadLibrary () в Delphi RTL вместо Win32 LoadLibrary. Эта функция сохраняет управляющее слово FP перед вызовом LoadLibrary и устанавливает его обратно в то, что Delphi хочет после возврата LoadLibrary.

6 голосов
/ 21 августа 2010

3221225616 = STATUS_FLOAT_INVALID_OPERATION. Я предполагаю, что FPU CW отличается в ваших приложениях Delphi и C, и что инициализация вашей DLL чувствительна к этому.

1 голос
/ 21 августа 2010

Я думаю, что вы должны сообщить разработчикам 3rdparty.dll об ошибке в их DLL.

0 голосов
/ 14 января 2016

Я знаю, что это старый поток, но я только что столкнулся с той же проблемой с DLL, написанной на VB.

Это решение работает как для x86, так и для x64

var  ret:cardinal;
     em:TArithmeticExceptionMask;
begin
  result:= 1;
  If Lib <> 0 Then exit;     // already loaded
  em:=GetExceptionmask;
  SetExceptionmask(em+[exInvalidOp,exZeroDivide,exOverflow, exUnderflow]);
  Lib := LoadLibrary(DLLname);
  SetExceptionmask(em);
  ret := GetLastError;
  if ret<>0 then
    raise exception.create(SysErrorMessage(ret));
...