Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.016 c
4-1140501309
npr2
2006-02-21 08:55
2006.05.14
дочернее окно


8-1134812696
Фео
2005-12-17 12:44
2006.05.14
Драм-машина


3-1142861160
Спрашивающий
2006-03-20 16:26
2006.05.14
NULL в запросе


15-1145471256
LexxX
2006-04-19 22:27
2006.05.14
Локализация "утечки" памяти


2-1145971001
Ice [greensky]
2006-04-25 17:16
2006.05.14
Как изменить цвет ячейки в stringgrid?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский