Форум: "Основная";
Текущий архив: 2011.10.30;
Скачать: [xml.tar.bz2];
ВнизОшибка при вызове dll Найти похожие ветки
← →
Вульфович Филипп (2010-04-05 12:43) [0]Добрый день! У меня есть dll, которая работает с некоторым устройством (пинпадом).
Я линкую ее статически:
//Создание служебного объекта
function eftp_create(szConfigPath: PChar):Pointer; stdcall; external DllLibraryName;
//Освобождение служебного объекта
procedure eftp_destroy(pvSelf:Pointer);stdcall; external DllLibraryName;
//Отправка-прием данных
function eftp_do(pvSelf:Pointer;pchInBuffer:PChar; pchOutBuffer:PChar;
pfldle:pointer;pvData:pointer):integer; stdcall; external DllLibraryName;
Я сделал тестовую программку: форму с кнопкой.
Проблема в том ,что
если я вызываю функции dll так:
procedure TForm1.Button1Click(Sender: TObject);
var
UcsObj: Pointer;
begin
UcsObj:=eftp_create(СonfigPath);
eftp_do(UcsObj, PChar(S1), S2, nil, nil);
eftp_destroy(UcsObj);
end;
То все работает прекрасно!
Но если я пытаюсь поместить процедуру eftp_create в другую процедуру, возникает ошибка "Privileged instruction", вот
код, который не работает:
procedure TForm1.Button1Click(Sender: TObject);
var
UcsObj: Pointer;
procedure CreateObj;
begin
UcsObj:=eftp_create(СonfigPath);
end;
begin
eftp_do(UcsObj, PChar(S1), S2, nil, nil);
eftp_destroy(UcsObj);
end;
При выполнении eftp_create ошибки не происходит, а ошибка Privileged Instruction возникает при выходе из процедуры Test.
То же самое, если я создаю служебный класс
interface
TEFTPServiceObject = class
private
UcsObj: Pointer;
public
procedure CreateObject(ConfigPath: string);
end;
implementation
procedure TEFTPServiceObject.CreateObject(ConfigPath: string);
begin
UcsObj:=eftp_create(СonfigPath);
end;
...
Вызов eftp_create нормально проходит внутри метода CreateObject, но после возвращения из
из метода CreateObject та же ошибка: Privileged Instruction
Помогите разобраться. Получается я не могу воспользоваться ни структурным программирование, ни тем более объектно-ориентированным.
Сейчас буду пробовать вызывать dll динамически через LoadLibrary, может быть заработает. Но хочется разобраться, почему и статическое линкование работает как-то очень плохо.
Спасибо!
← →
Slym © (2010-04-05 13:15) [1]судя по всему содержимое СonfigPath в eftp_create не копируется, а сохраняется ссылка...
при выходе из процедуры строка затирается...
прпробуй глобально объявить:
var СonfigPath="c:\"; или const СonfigPath="c:\";
илиTEFTPServiceObject = class
private
FСonfigPath:string;
UcsObj: Pointer;
public
procedure CreateObject(const ConfigPath: string);
end;
procedure TEFTPServiceObject.CreateObject(const ConfigPath: string);
begin
FСonfigPath:=ConfigPath;
UcsObj:=eftp_create(FСonfigPath);
end;
← →
Вульфович Филипп (2010-04-05 13:42) [2]Да, но так тоже не работает! Куда проще?
procedure TForm1.Button1Click(Sender: TObject);
var
UcsObj: Pointer;
procedure CreateObj;
begin
UcsObj:=eftp_create("C:\test.cfg");
end;
begin
CreateObj;
eftp_do(UcsObj, PChar(S1), S2, nil, nil);
eftp_destroy(UcsObj);
end;
← →
Игорь Шевченко © (2010-04-05 13:57) [3]UniqueString не спасет ?
← →
Дмитрий Белькевич (2010-04-05 14:39) [4]
> При выполнении eftp_create ошибки не происходит, а ошибка
> Privileged Instruction возникает при выходе из процедуры
> Test.
Есть подозрение, что проблема в передаче параметров в/из длл.
Скорее всего рушится стёк.
← →
12 © (2010-04-05 15:38) [5]
> procedure CreateObj;
> begin
> UcsObj:=eftp_create("C:\test.cfg");
> end;
=eftp_create(Pchar("C:\test.cfg")); ?
← →
Вульфович Филипп (2010-04-05 17:43) [6]
> Есть подозрение, что проблема в передаче параметров в/из
> длл.
>
> Скорее всего рушится стёк.
Так и есть. Нужно было переопределить функции:
//Создание служебного объекта
function eftp_create(szConfigPath: PChar):Pointer; cdecl; external DllLibraryName;
//Освобождение служебного объекта
procedure eftp_destroy(pvSelf:Pointer);cdecl; external DllLibraryName;
//Отправка-прием данных
function eftp_do(pvSelf:Pointer;pchInBuffer:PChar; pchOutBuffer:PChar;
pfldle:pointer;pvData:pointer):integer; cdecl; external DllLibraryName;
Но как я мог подумать, что разработчик dll будет cdecl, вместо стандартной stdcall?
:)
← →
Дмитрий Белькевич (2010-04-05 18:22) [7]
> Но как я мог подумать, что разработчик dll будет cdecl,
> вместо стандартной stdcall?
Бывает ;) Когда валится на end"ах - верный признак, что стёк кто-то рушит.
← →
Игорь Шевченко © (2010-04-05 19:47) [8]Never attribute to malice which can adequately be explained by stupidity
← →
Германн © (2010-04-06 01:32) [9]
> Но как я мог подумать, что разработчик dll будет cdecl,
> вместо стандартной stdcall?
Если я не ошибаюсь, то если в Си не указывать явно соглашение о вызовах, то будет именно cdecl. А в Delphi будет pascal. И об этом нужно всегда помнить, если речь идет о нестандартных dll.
← →
Amoeba_ (2010-04-06 12:03) [10]
> А в Delphi будет pascal.
Слегка ошибаешься. По умолчанию в Delpi будет register а не pascal.
← →
evvcom © (2010-04-07 11:10) [11]По-моему, это называется fastcall
← →
Amoeba_ (2010-04-07 11:45) [12]
> evvcom © (07.04.10 11:10) [11]
И то и другое правильно. register и fastcall - это всего лишь разные названия одного и того же способа передачи параметров. В старых версиях Delphi - register, в более новых - переименовали в fastcall.
← →
evvcom © (2010-04-08 09:52) [13]Старые, более новые - понятия весьма расплывчатые...
По-моему, название fastcall я вычитывал еще в какой-то книжке по Delphi 2, а уж 2-ю версию никак не назовешь более новой, хотя могу и ошибаться, столько лет уже прошло, может и позже читал. А про register тоже где-то читал, уже толком не помню что и из-за того, что этот термин практически не употреблялся, деталей про него не помню. Хотя да, было в памяти, что это или то же самое или очень похожее на fastcall :)
← →
Amoeba_ (2010-04-08 12:25) [14]Ну, возможно, было и наоборот. Во всяком случае, начиная с D4 используется название register.
fastcall - это тот же самый register, кроме как в названии абсолютно никакой разницы нет.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2011.10.30;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.004 c