Форум: "Начинающим";
Текущий архив: 2006.05.14;
Скачать: [xml.tar.bz2];
Внизdll и экспортируемые функции Найти похожие ветки
← →
parovoZZ © (2006-04-23 04:22) [0]Есть такое
library Errors;
uses
Windows;
{$I asm.inc}
function Errors_ (Handle : THandle; NativeError : integer) : boolean; stdcall export;
var
ExceptionMessage : string;
begin
result := false;
if NativeError <= 0 then exit;
result := true;
case NativeError of
1045 : ExceptionMessage := "текст";
2003 : ExceptionMessage := "<текст>";
2006,
2013 : ExceptionMessage := "text";
else
ExceptionMessage := "text" + Int2Str (NativeError);
end;
MessageBox (Handle, Pointer (ExceptionMessage), nil, MB_ICONSTOP);
end;
exports
Errors_ name "Errors_dll";
begin
end.
в приложении
type
TImportProc = function (Handle : THandle; ErroreNative : integer) : boolean; stdcall;
........
procedure TMainForm.Exception (Err : integer);
var
ImportProc : TImportProc;
Handle : THandle;
Mess : string;
begin
Handle := LoadLibrary ("DATA/Errors");
if Handle <= HINSTANCE_ERROR then
begin
Mess := "/////";
MessageBox (Handle, Pointer (Mess), nil, MB_ICONERROR);
exit;
end;
@ImportProc := GetProcAddress (Handle, "Errors_dll");
if @ImportProc <> nil then ImportProc (MainForm.Handle, Err);
FreeLibrary (Handle);
end;
Почему-то без волшебного слова stdcall не работает? Ругается на Access violatin....
и потом - для каждой экспортируемой функции надо объявлять тип? Тогда может проще использовать статический метод?
← →
TUser © (2006-04-23 06:42) [1]> и потом - для каждой экспортируемой функции надо объявлять тип?
И для неэкспортируемой тоже :)
А соглашения о вызовах должны быть одинаковы - в библиотеке у тебя stdcall.
← →
parovoZZ © (2006-04-23 14:20) [2]
> А соглашения о вызовах должны быть одинаковы - в библиотеке
> у тебя stdcall.
А без него никак?
← →
begin...end © (2006-04-23 14:52) [3]> parovoZZ © (23.04.06 14:20) [2]
При загрузке библиотеки (LoadLibrary) она отображается в память программы, т.е. после этого код библиотеки (всех экспортируемых ею подпрограмм) оказывается где-то в памяти Вашей программы. Вызывая GetProcAddress, Вы получаете конкретный адрес начала кода нужной подпрограммы (и сохраняете его в переменной ImportProc). Чтобы вызвать подпрограмму, нужно передать управление по этому адресу.
Но перед этим нужно ещё подготовить для неё параметры. Их можно передавать через регистры или через стек. Если они передаются через стек, его после завершения работы подпрограммы нужно очистить -- это может сделать либо сама эта подпрограмма, либо Ваше приложение.
Но обо всём этом нужно договориться. Если перед вызовом подпрограммы её параметры будут сохранены в стеке, то и сама подпрограмма должна знать, что их нужно брать именно оттуда, а не из регистров. Если Ваше приложение рассчитывает на то, что стек будет очищен самой подпрограммой, то и сама подпрограмма должна знать, что его нужно очистить.
Так вот -- все эти договорённости как раз и определяются соглашением о вызове (stdcall, cdecl, register и т.д.). Они должны быть одинаковыми в библиотеке и хост-приложении. Например, если мы в приложении укажем stdcall, то это будет означать, что перед вызовом DLL-подпрограммы параметры будут переданы через стек, который будет очищаться вызываемой подпрограммой. А чтобы подпрограмма "знала" об этом и вела себя соответствующим образом, нужно указать stdcall и в библиотеке.
Если не указать соглашение явно, то будет использоваться соглашение register, при котором первые три параметра передаются через регистры. Если DLL будет использоваться только в Delphi, имеет смысл указать register (или не указывать вообще ничего). Это соглашение работает несколько быстрее, чем соглашения, использующие стек.
Если же DLL планируется использовать, например, в C, то следует указать stdcall. Но, разумеется, указать и в библиотеке, и в приложении.
← →
DrPass © (2006-04-23 22:58) [4]
> parovoZZ © (23.04.06 14:20) [2]
Самое непонятное в твоей проблеме - чем тебе мешает слово stdcall???
Можно и без него - главное, чтобы соглашение о вызове было одинаковым и в библиотеке, и в программе. Т.е. просто убери stdcall в обоих исходниках, и все будет работать. Кстати, слово export там тоже лишнее - эта директива просто игнорируется современным компилятором
← →
parovoZZ © (2006-04-24 19:57) [5]Т. е. тип функции надо всегда объявлять?
Кстати, нашёл ошибку - препутал NativeError и ErroreNative...Теперь работает и без stdcall и без export.
Всем спасибо за развёрнутые ответы.
← →
Гаврила © (2006-04-24 20:02) [6]
> Кстати, нашёл ошибку - препутал NativeError и
> ErroreNative
В смысле??
Ты что, думаешь, что названия параметров имеют какое-то значение?
)
← →
parovoZZ © (2006-04-25 20:10) [7]Хм, действительно, работает с любым параметром. А что ж тогда было, если без stdcall не работало???
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.05.14;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.009 c