Форум: "Начинающим";
Текущий архив: 2006.08.06;
Скачать: [xml.tar.bz2];
ВнизТипы в Dll Найти похожие ветки
← →
!_SM_! (2006-07-19 20:15) [0]Есть DLL (моя) в ней описан тип
TInfo = record
Name, Author: String;
end;
есть процедура
procedure GetInfo(var Inf: TInfo); stdcall; export;
begin
Inf.Name:="Name";
Inf.Author:="Author";
end;
в ехе описан тот-же тип
TInfo = record
Name, Author: String;
end;
описана переменная
var GetInfo: procedure (var Inf: TInfo); stdcall;
из ехе динамически гружу dll"ку получаю указатель на процедуру, вызываю ее
HDll:=LoadLibrary(PChar(<путь и имя dll>));
if HDll<>0 then begin
@GetInfo:=GetProcAddress(HDll, "GetInfo");
if @GetInfo=nil then FreeLibrary(HDll) else
begin
SetLength(Inf.Name, 50);
SetLength(Inf.Author, 50);
GetInfo(Inf);
ShowMessage(Inf.Name);
end;
end;
получаю AV. Как это обойти и желательно без использования ShareMem?
← →
!_SM_! (2006-07-19 20:19) [1]AV на строке GetInfo(Inf);
← →
StriderMan © (2006-07-19 21:11) [2]вместо
> var GetInfo: procedure (var Inf: TInfo); stdcall;
надоtype
TGetInfoProc = procedure (var Inf: TInfo); stdcall;
var
GetInfo: TGetInfoProc ;
далее
...GetInfo:=GetProcAddress(HDll, "GetInfo");
if Assigned(GetInfo) then
....
← →
Zeqfreed © (2006-07-19 21:15) [3]ShareMem ещё не забыть.
← →
Rial © (2006-07-19 21:18) [4]Если тебе не нравится ShareMem, то не используй стринги.
Сделай хотябы
TInfo = record
Name, Author: PChar;
end;
С указателями проблем не будет.
Или вообще
TInfo = record
Name, Author: Pointer;
end;
Размещай даные строк в память по указателю, запоминай размер и передавай.
← →
StriderMan © (2006-07-19 21:20) [5]а может вообще сделать
PInfo = ^TInfo;
и его использовать
← →
sniknik © (2006-07-19 21:23) [6]> Как это обойти и желательно без использования ShareMem?
TInfo = record
Name, Author: String[50];
end;
ну и естественно убрать
SetLength(Inf.Name, 50);
SetLength(Inf.Author, 50);
← →
!_SM_! (2006-07-19 21:55) [7]
> StriderMan © (19.07.06 21:11) [2]
> type TGetInfoProc = procedure (var Inf: TInfo); stdcall;
> var GetInfo: TGetInfoProc ;
А это разве не одно и тожеvar GetInfo: procedure (var Inf: TInfo); stdcall;
??????
> sniknik © (19.07.06 21:23) [6]
Не работает.
Вот как делаю:
переделал
type
TInfo = record
Name, Author: String[50];
end;
TGetInfo = procedure (var Inf: TInfo); stdcall;
var GetInfo: TGetInfo;
........
procedure TForm1.FormCreate(Sender: TObject);
var SR: TSearchRec;
N, HDLL: Integer;
Inf: TInfo
procedure AddInf(const FDll: String);
begin
HDll:=LoadLibrary(PChar(FDll));
if HDll<>0 then begin
@GetInfo:=GetProcAddress(HDll, "GetInfo");
if @GetInfo=nil then FreeLibrary(HDll)
else begin
GetInfo(Inf);
ShowMessage(Inf.Name);
end;
end else FreeLibrary(HDll);
end;
begin
N:=FindFirst("*.dll", faAnyFile, SR);
while N=0 do begin
AddInf(SR.Name);
N:=FindNext(SR);
end;
FindClose(SR);
end;
При условии что есть более 1 DLL (подходящих)
показывает 1 раз ShowMessage(Inf.Name);
и AV.
Если закомментировать//GetInfo(Inf);
//ShowMessage(Inf.Name);
и вставитьShowMessage(FDll);
то ошибки нет показываются все имена Dll"ек.
← →
!_SM_! (2006-07-19 21:58) [8]В библиотеке тоже переделал
TInfo = record
Name, Author: String[50];
end;
← →
sniknik © (2006-07-19 22:55) [9]> показывает 1 раз ShowMessage(Inf.Name);
> и AV.
одну dll исправил, и она первая находится, остальные нет...
← →
!_SM_! (2006-07-19 23:04) [10]Блин, ведь остальные просто копии были.... правильно.... сейчас попробую
сделал еще такtype TAvtInfo = record
Name, CopyR: PChar;
end;
сейчас попробую, отпишусь
← →
!_SM_! (2006-07-19 23:05) [11]Блин, ведь остальные dll просто копии были (неправильные).... правильно.... сейчас попробую
сделал еще такtype TAvtInfo = record
Name, CopyR: PChar;
end;
сейчас попробую, отпишусь
← →
!_SM_! (2006-07-19 23:07) [12]Все нормально с PChar"ом
← →
!_SM_! (2006-07-19 23:08) [13]Все нормально с PChar"ом без ShareMem"a.
Спасибо всем.
← →
GL00m (2006-07-20 00:50) [14]Если не возражаете, я присоединюсь к дискуссии - у меня проблема со схожими исходными данными:
имеетсяtype MyMessage = record
myID : PChar;
end;
PMyMessage = ^MyMessage;
которые также описаны и в DLL-ке и в проекте. В длл-ке есть функцияMyMsgUnpack(s : PChar) : PMyMessage
.
Я делаю все то же, что и выше описано:var rez : MyMessage;
...
h := LoadLibrary(PChar("file.dll"));
@f := GetProcAddress(h,"MyMsgUnpack");
p := PChar(data);
pmsg := f(p);
rez := pmsg^;
FreeLibrary(h);
До этого момента все ОК. Но! Как только я делаю что-то вродеLabel1.Caption := rez.MyID;
, то получаю AV и чё за фигня - не пойму. =( Не подскажете, куда копать?
← →
Юрий Зотов © (2006-07-20 02:37) [15]> GL00m (20.07.06 00:50) [14]
Где и как выделяется память под запись, адрес которой возвращает DLL и под строку в этой записи?
← →
GL00m (2006-07-20 11:13) [16]В общем-то нигде, это все. Т.е. просто
var rez : MyMessage; pmsg : PMyMessage;
Дальше тело, которое я написал:h := LoadLibrary(PChar("file.dll"));
итд. В DLL-е в функции MyMsgUnpack сначалаvar msg : MyMessage;
Потомmsg.myID := PChar("smthn");
а затемResult := @msg
Причем, если в запись MyMessage добавить, например,i : Integer
, то с ним все работает нормально, а вот с PChar-ом - AV.
← →
StriderMan © (2006-07-20 12:39) [17]
> !_SM_! (19.07.06 21:55) [7]
> > StriderMan © (19.07.06 21:11) [2]
> > type TGetInfoProc = procedure (var Inf: TInfo); stdcall;
> > var GetInfo: TGetInfoProc ;
> А это разве не одно и тоже
> var GetInfo: procedure (var Inf: TInfo); stdcall;
> ??????
по сути да. но это более правильный подход. (не ИМХО). Не зря ведь в делфи процедурные типы сделали?
благодаря такому подохду не нужны вот эти пляски с бубном:
> @GetInfo:=GetProcAddress(HDll, "GetInfo");
> if @GetInfo=nil then FreeLibrary(HDll) else
← →
sniknik © (2006-07-20 13:21) [18]> благодаря такому подохду не нужны вот эти пляски с бубном:
>> @GetInfo:=GetProcAddress(HDll, "GetInfo");
>> if @GetInfo=nil then FreeLibrary(HDll) else
как это не нужны? нужны, это же получение и проверка на существование экспортной функции (вполне можно "зацепить" и не свою dll где ее не будет), и эта проверка совсем не зависит от того как именно задана процедурная переменная. (через предварительно описанный тип, или непосредственно у переменной)
а вот переписать в более понятном виде не помешает... типа
(писал тут, возможны ошибки, поправте если что)procedure TForm1.FormCreate(Sender: TObject);
var SR: TSearchRec;
procedure AddInf(const FDll: String);
var
HDLL: Integer;
Inf: TInfo
begin
HDll:= LoadLibrary(PChar(FDll));
if HDll <= 32 then RaiseLastOSError;
try
@GetInfo:= GetProcAddress(HDll, "GetInfo");
if @GetInfo <> nil then begin
GetInfo(Inf);
ShowMessage(Inf.Name);
end;
finally
FreeLibrary(HDll)
end;
end;
begin
if FindFirst("*.dll", faAnyFile, SR) = 0 then begin
repeat
AddInf(SR.Name);
until FindNext(SR) <> 0;
FindClose(SR);
end;
end;
← →
StriderMan © (2006-07-20 13:28) [19]
> как это не нужны? нужны, это же получение и проверка на
> существование экспортной функции (вполне можно "зацепить"
> и не свою dll где ее не будет), и эта проверка совсем не
> зависит от того как именно задана процедурная переменная.
> (через предварительно описанный тип, или непосредственно
> у переменной)
а проверка
> @GetInfo <> nil
всегда даст true. Ведь переменная GetInfo уже объявлена, адрес ее известен. чтобы в этом убедиться предлагаю маленький тест:procedure TForm1.Button1Click(Sender: TObject);
var
P: Pointer;
begin
ShowMessage(IntToStr(integer(@P)));
end;
Вот более простой, прозрачный и правильный код
> GetInfo:=GetProcAddress(HDll, "GetInfo");
> if Assigned(GetInfo) then
← →
GL00m (2006-07-20 13:53) [20]Я опять встряну со своей проблемой, если не возражаете. =)
Переделал я немного свои функции, сделал выделение памяти:
type
TMyMsgUnpack=procedure(m:PChar;var pm:PMyMessage);
MyMessage = record
myID : PChar;
myCount : Integer;
end;
...
var
m : MyMessage;
pm : PMyMessage;
h : Integer;
f : TMyMsgUnpack
begin
pm := AllocMem(SizeOf(m));
h := LoadLibrary("file.dll");
@f := GetProcAddress(h,"MyMsgUnpack");
p := PChar("somedata");
f(p,pm);
FreeLibrary(h);
FreeMem(pm,SizeOf(m));
end;
Процедура MyMsgUnpack лежит в DLL-ке, в ней делается что-то типа:pm^.myID := PChar("Hello");
pm^.myCount := 5;
Так вот в моей функции после строчкиf(p,pm);
получается:pm^.myID = "Hello"
pm^.myCount = 5
, но сразу послеFreeLibrary(h);
myID становится равным "", а myCount остается 5. Что я не так делаю?
← →
sniknik © (2006-07-20 14:30) [21]> а проверка
>> @GetInfo <> nil
> всегда даст true. Ведь переменная GetInfo уже объявлена, адрес ее известен. чтобы в этом убедиться предлагаю маленький
> тест:
в свою очередь предлагаю немного изменить этот маленький тест... ;)
type
TInfo = record
Name, Author: String[50];
end;
TGetInfoProc = procedure (var Inf: TInfo); stdcall;
....
var
Form1: TForm1;
GetInfo1: procedure (var Inf: TInfo); stdcall; //это то что у него было
GetInfo2: TGetInfoProc; //это посоветовано тобой
//(правильно в принципе посоветовано, но причина зачем это делать немного "не та" должна быть)
procedure TForm1.Button1Click(Sender: TObject);
var
P: Pointer;
begin
ShowMessage(IntToStr(Integer(@P))+" : "+IntToStr(Integer(@GetInfo1))+" : "+IntToStr(Integer(@GetInfo2)));
end;
смотри разницу. (вернее ее отсутствие ;)
> Я опять встряну со своей проблемой, если не возражаете. =)
не парься, сделай на коротких строках, если не умееш с PChar работать. ([6])
> Что я не так делаю?
память под myID не выделил, и данные в нее не записал, вместо этого присвоил указатель переменной из модуля.
← →
StriderMan © (2006-07-20 14:41) [22]
> смотри разницу. (вернее ее отсутствие ;)
да, слушай, ты прав! Я и забыл что переменная процедурного типа ведет себя не как pointer.
Но все же меня смущает присвоение ей адреса процедуры через оператор взятия адреса (@).
Я обычно делаю как описал и никаких "собачек" не нужно. и проверка Assigned() вроде специально для этого придумана.
← →
GL00m (2006-07-20 14:50) [23]to sniknik:
Черт! Видимо спать надо больше: я был уверен, что с ShortString я уже пробовал и было то же самое. Сейчас сделал и все получилось. Спасибо!
> память под myID не выделил, и данные в нее не записал, вместо
> этого присвоил указатель переменной из модуля
Память выделить - это через StrAlloc? А то, что я присвоил указатель, вместо записи данных - надо было делать StrPCopy(pm^.myID,"Hello") ?
(это я для самообразования на будущее =))
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.08.06;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.021 c