В настоящее время я пишу модуль, который взаимодействует с черным ящиком сторонней DLL для проверки сканера. Мне нужно, чтобы функции DLL загружались динамически, и это работает для всех, кроме одной функции.
Функция SetScanParameters имеет структуру записи в качестве параметра, которая, как мне кажется, каким-то образом мешает методологии, которую я использую, для ее динамической загрузки (см. Ниже). При динамической загрузке функция прерывается нарушением доступа.
SetScanParameters действительно загружается и функционирует должным образом при статической загрузке. Есть ли что-то еще, что мне нужно сделать для динамической загрузки функции с помощью структуры записи?Delphi: Почему я могу связать эту функцию статически, но не динамически?
самостоятельно отредактированы для ясности:
Тип записи:
TBK_ScanParameter=packed record
Left:short;
Top:short;
Width:short;
Length:short;
//
xResolution:short;
yResolution:short;
BitsPerPixel:short;
LightControl:short;
MotorControl:short;
//
rGain:short;
gGain:short;
bGain:short;
rOffset:short;
gOffset:short;
bOffset:short;
rExposure:short;
gExposure:short;
bExposure:short;
//
FeedDirection:short;
CropImage:short;
ScanWithMICR:short;
//
Reserved:array [0..14] of short;
end;
Статическая декларация:
function BK_SetScanParameter(var ScanParameter:TBK_ScanParameter):integer; cdecl;
Статическая реализация:
function BK_SetScanParameter(var ScanParameter:TBK_ScanParameter):integer; cdecl; external 'BKV2.dll' name '[email protected]';
Динамическая логика (или что чюо ÜLD быть динамической логики, если я не должен использовать статический вызов, чтобы сделать его работу):
function TdmScannerV2.SetScanParameter(pScanParameter: TBK_ScanParameter): string;
type
TBK_SetScanParameter = function (var ScanParameter:TBK_ScanParameter):integer; stdcall;
var
hV2Dll:HMODULE;
func:TBK_SetScanParameter;
begin
hV2Dll:=0;
result := '';
try
hV2Dll:=LoadLibrary('BKV2.dll');
if hV2Dll>0 then
begin
@func:=GetProcAddress(hV2Dll, '[email protected]');
if Assigned(@func) then
begin
try
if BK_SetScanParameter(pScanParameter) > 0 then {This one works, but is static}
//if func(pScanParameter) > 0 then {this one gets an AV}
begin
Result := 'Y:Scan Parameters Set';
end
else
Result := 'ERROR:Failure code returned';
{
if func(pScanParameter) > 0 then
Result := 'Y:Scan Parameters Set'
else
Result := 'ERROR:Failure code returned';
}
except
on e:Exception do
begin
Result := 'ERROR:Exception:' + e.Message;
end;
end;
end
else
Result := 'ERROR:Unable to load BK_SetScanParameter';
end
else
Result := 'ERROR:Unable to load BKV2.dll';
finally
if hV2Dll>0 then FreeLibrary(hV2Dll);
end;
end;
И я попытался с помощью STDCALL, Cdecl, директивой SafeCall, паскаль, и зарегистрировать на динамику и все они привели к AV. Я также попытался сделать массив в структуре [1..15] вместо [0..14]. И в Но я не получаю, если я передаю структуру в статическую версию, она работает.
Кроме того, в OP было несколько опечаток, и я прошу прощения за это. Я переписывал код в OP и делал несколько опечаток, которые немного мутировали поток. Я заменил его копией/вставкой текущей тестовой функции.
редактирования: Ниже ЬурейеЕ, как описано в документации для DLL:
typedef struct ScanParameter
{
short Left; // left start positsion
short Top; // top start positsion
short Width; // scan image width in 1/100 inch
short Length; // scan image length in 1/100 inch
short xResolution; // horizontal resolution
short yResolution; // vertical resolution
short BitsPerPixel; // 24bit color, 8bit gray
short LightControl; // 0 - All lamp Off, 1 - red, 2 - green, 3 - blue, 4 - All lamp On
short MotorControl; // Motor Control, 0 - off, 1 = on
short rGain; // AFE R-Gain
short gGain; // AFE G-Gain
short bGain; // AFE B-Gain
short rOffset; // AFE R-Offset
short gOffset; // AFE G-Offset
short bOffset; // AFE B-Offset
short rExposure; // AFE R-Exposure
short gExposure; // AFE G-Exposure
short bExposure; // AFE B-Exposure
short FeedDirection; // feedout paper direction, 0 –fordward, 1 - backward
short CropImage; // 0 - no trim edge , 1 - trim edge
short ScanWithMICR; // 0 –off, 1 –scan image until paper leave device
short Reserved[15];
} ScanParameter;
Добро пожаловать в Переполнение стека. Вы должны быть более точными. Если GetProcAddress завершается успешно, то вы загрузили функцию, поэтому ваш заголовок просто неверен. Кроме того, вы не можете «загружать» функцию статически. Здесь нет ничего статического. DLL * всегда * связаны динамически. Вот что означает * D *. Различие между динамическими связями * load-time * и * run-time *. Время загрузки - это когда ОС считывает таблицу импорта вашей программы и разрешает вам адреса функций, поскольку она загружает программу в память. Время запуска - это когда вы загружаете модуль и выбираете адрес непосредственно с помощью GetProcAddress. –
Ваша статическая динамика - как яблоки для апельсинов. Одна из них - это функция cdecl из Scan.dll, другая - функция stdcal из ScanDLL.dll. Или вы не опубликовали свой реальный код .... –
Итак, из документации, похоже, DLL была написана на C. Возможно ли получить исходное объявление функции DLL? Кроме того ... Хотя я немного ржавый на C нюансах, я вполне уверен, что 'short Reserved [15];' должен быть записан как 'Reserved: array [0..15] short;' в Delphi. –