type
TProc = function(Message:PChar): Integer;
var
h: THandle;
proc: TProc;
begin
h := LoadLibrary( 'MyPlugin.dll' );
if h <> INVALID_HANDLE_VALUE then
begin
proc := GetProcAddress( h, 'MyProc' );
if @proc <> Nil then
begin
proc( 'Hello World!' );
end;
FreeLibrary( h );
end;
end;
поддержка плагинов (DLL)
как можно динамически подключть DLL. (прикол, динамически подключть динамичаски подключаемую библеотеку =))
LoadLibrary, GetProcAddress.
и FreeLibrary потом обязательно, т.е. когда с длл отработаешь и она больше не нужна станет.
так... длл вызвал.... а как теперь вызвать из неё метод? поподробнее, пжалста.
[QUOTE=sql-injection]так... длл вызвал.... а как теперь вызвать из неё метод? поподробнее, пжалста.[/QUOTE]
Код:
type
TProc = function(Message:PChar): Integer;
var
h: THandle;
proc: TProc;
begin
h := LoadLibrary( 'MyPlugin.dll' );
if h <> INVALID_HANDLE_VALUE then
begin
proc := GetProcAddress( h, 'MyProc' );
if @proc <> Nil then
begin
proc( 'Hello World!' );
end;
FreeLibrary( h );
end;
end;
TProc = function(Message:PChar): Integer;
var
h: THandle;
proc: TProc;
begin
h := LoadLibrary( 'MyPlugin.dll' );
if h <> INVALID_HANDLE_VALUE then
begin
proc := GetProcAddress( h, 'MyProc' );
if @proc <> Nil then
begin
proc( 'Hello World!' );
end;
FreeLibrary( h );
end;
end;
А как быть, если неизвестно имя функции в DLL???
если уж мы рассматриваем поддержку плагинов, то имя процедуры или функции определяет человек, который написал программу, а не те кто пишет для неё плагины, соответственно его прога будет знать опред. имя вызываемой функции/процедуры, будет sdk и те кто хочет добавить примочку к программе могут писать плагин опираясь на sdk и называть функции так как написано в sdk, поэтому код самое то.
слушайте... чота, блин, не работает.... выдеёт исключение (ошибка ввода-вывода)... что делать?
Код:
var MyMsgBox:function(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer;stdcall;
hLib:DWORD;
begin
hLib := LoadLibrary('user32.dll');
if hLib <> INVALID_HANDLE_VALUE then
begin
MyMsgBox:= GetProcAddress( hLib, 'MessageBoxA' );
if @MyMsgBox <> Nil then
begin
MyMsgBox(0,'','',0 );
end;
FreeLibrary( hLib );
end;
end;
hLib:DWORD;
begin
hLib := LoadLibrary('user32.dll');
if hLib <> INVALID_HANDLE_VALUE then
begin
MyMsgBox:= GetProcAddress( hLib, 'MessageBoxA' );
if @MyMsgBox <> Nil then
begin
MyMsgBox(0,'','',0 );
end;
FreeLibrary( hLib );
end;
end;
просто решил показать на уже существующей длл.
описал функцию, загрузил длл, а как пытаюсь вызвать метод - ашыпка.
вот исходник
Код:
type
TProc = function:TStrings;
var
hLib: THandle;
AboutEx: TProc;
procedure TForm2.Button1Click(Sender: TObject);
begin
with OpenDialog1 do
if execute then edit1.Text:=filename;
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
if fileexists(edit1.Text) then
begin
hlib := LoadLibrary(PChar(Edit1.Text));
if hlib <> INVALID_HANDLE_VALUE then
begin
AboutEx := GetProcAddress( hlib, 'AboutEx' );
if @AboutEx <> Nil then
begin
ListBox1.Items:=AboutEx;
end
else MessageDlg('В данном файле нет метода AboutEx. Плохая библиотека =(',mtError,[mbOk],0);
FreeLibrary(hlib);
end
else MessageDlg('Неверный Handle. Плохая библиотека =(',mtError,[mbOk],0);
end
else MessageDlg('Нет такого файла =(',mtError,[mbOk],0);
end;
TProc = function:TStrings;
var
hLib: THandle;
AboutEx: TProc;
procedure TForm2.Button1Click(Sender: TObject);
begin
with OpenDialog1 do
if execute then edit1.Text:=filename;
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
if fileexists(edit1.Text) then
begin
hlib := LoadLibrary(PChar(Edit1.Text));
if hlib <> INVALID_HANDLE_VALUE then
begin
AboutEx := GetProcAddress( hlib, 'AboutEx' );
if @AboutEx <> Nil then
begin
ListBox1.Items:=AboutEx;
end
else MessageDlg('В данном файле нет метода AboutEx. Плохая библиотека =(',mtError,[mbOk],0);
FreeLibrary(hlib);
end
else MessageDlg('Неверный Handle. Плохая библиотека =(',mtError,[mbOk],0);
end
else MessageDlg('Нет такого файла =(',mtError,[mbOk],0);
end;
Код:
type
TProc = function:TStrings;stdcall;
TProc = function:TStrings;stdcall;
Если хочешь, можешь возвращать из DLL вместо TStrings строку типа PChar, которая равна TStrings.DelimitedText. А уже в EXE преобразовывать ее обратно в TStrings.
Код:
type
TProc = function:TStrings;stdcall;
TProc = function:TStrings;stdcall;
пробовал - не пашет (ошибка при обращении по нулевому указателю) =(
Если хочешь, можешь возвращать из DLL вместо TStrings строку типа PChar, которая равна TStrings.DelimitedText. А уже в EXE преобразовывать ее обратно в TStrings.[/QUOTE]
с пакетами всё в норме.
В основной программе:
Код:
unit myunit;
interface
uses
Windows, Classes, Messages, SysUtils;
type
TFunc = procedure(); stdcall;
var
myfunc : TFunc;
implementation
procedure TForm1.LoadLib();
begin
hlib := LoadLibrary(PChar('mylib.dll'));
if hlib <> INVALID_HANDLE_VALUE then
begin
@myfunc := GetProcAddress( hlib, 'exportfunc' );//обратить внимание на знак @
if Assigned(myfunc) <> Nil then
begin
myfunc();
end
else
ShowMessage('облом');
FreeLibrary(hlib);
end
else
ShowMessage('облом');
end;
interface
uses
Windows, Classes, Messages, SysUtils;
type
TFunc = procedure(); stdcall;
var
myfunc : TFunc;
implementation
procedure TForm1.LoadLib();
begin
hlib := LoadLibrary(PChar('mylib.dll'));
if hlib <> INVALID_HANDLE_VALUE then
begin
@myfunc := GetProcAddress( hlib, 'exportfunc' );//обратить внимание на знак @
if Assigned(myfunc) <> Nil then
begin
myfunc();
end
else
ShowMessage('облом');
FreeLibrary(hlib);
end
else
ShowMessage('облом');
end;
В библиотеке:
Код:
library mylib;
uses
Windows;
procedure exportfunc();
begin
MessageBox(0,'Hello world!!!','Message',MB_OK);
end;
exports
exportfunc;
end.
uses
Windows;
procedure exportfunc();
begin
MessageBox(0,'Hello world!!!','Message',MB_OK);
end;
exports
exportfunc;
end.
надо длл посмотреть. можно код или уже готовую.
а в конце кода длл надо писать exports и т.д. (я написал) ?
Цитата: kosfiz
опиши поподробнее, что ты делал, т.е. какую функцию/процедуру вызывал из какой дллшки и т.д. кстати вот код, показывающий как из user32.dll можно вызвать функцию MessageBox:
просто решил показать на уже существующей длл.
Код:
var MyMsgBox:function(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer;stdcall;
hLib:DWORD;
begin
hLib := LoadLibrary('user32.dll');
if hLib <> INVALID_HANDLE_VALUE then
begin
MyMsgBox:= GetProcAddress( hLib, 'MessageBoxA' );
if @MyMsgBox <> Nil then
begin
MyMsgBox(0,'','',0 );
end;
FreeLibrary( hLib );
end;
end;
hLib:DWORD;
begin
hLib := LoadLibrary('user32.dll');
if hLib <> INVALID_HANDLE_VALUE then
begin
MyMsgBox:= GetProcAddress( hLib, 'MessageBoxA' );
if @MyMsgBox <> Nil then
begin
MyMsgBox(0,'','',0 );
end;
FreeLibrary( hLib );
end;
end;
просто решил показать на уже существующей длл.
Извеняюсь, что не в тему. )))
А почему именно "MessageBoxA", а не "MessageBox" или "MessageBoxB" (они в user32.dll помойму есть...)?
Например, MessageBoxA - ansi версия, MessageBoxW - соответственно unicode версия. И где ты там MessageBoxB нашёл? :) Хотя мона импортировать и MessageBox вроде... :)
[quote=sql-injection]а в конце кода длл надо писать exports и т.д. (я написал) ?[/quote]
конечно надо.
misha_turist
вот часть ответа на вопрос:
[quote=Релорт]В Windows API многие функции встречается в 2-х экземплярах: ANSI и UNICODE. Первые обозначаются суффиксом A, вторые – суффиксом W.
Например, MessageBoxA - ansi версия, MessageBoxW - соответственно unicode версия.[/quote]
а теперь про:
[quote=misha_turist]а не "MessageBox" или "MessageBoxB" (они в user32.dll помойму есть...)?[/quote]
нет, таких функций там нету, посмотри таблицу экспорта user32.dll(воспользуйся PEiD'ом или еще чем-нить).
Цитата: kosfiz
нет, таких функций там нету, посмотри таблицу экспорта user32.dll(воспользуйся PEiD'ом или еще чем-нить).
Я уже понял, я просто не помнил точно с какими на конце буквами я подобные функции видел.))