Текущий архив: 2006.04.23;
Скачать: CL | DM;
ВнизНе пойму где ошибка (вызов функции из DLL) Найти похожие ветки
← →
Хинт © (2006-03-30 18:26) [0]
function hGetLastError: PChar;
var
DLL: THandle;
hFunc: function: PChar;
begin
Result := "";
DLL := LoadLibrary(PChar("hToPr.dll"));
if (DLL = 0) then
begin
Result:="hToPr: ошибка загрузки библиотеки";
Exit;
end;
try
@hFunc := GetProcAddress(DLL, "hGetLastError");
if Assigned(@hFunc) then Result:=hFunc else Result:="hToPr: не найдена искомая функция";
finally
FreeLibrary(DLL);
end;
end;
При вызове функции ShowMessage(GetLastError) вылетает ошибка "Access violation at address...". В чем тут ошибка?
← →
Хинт © (2006-03-30 18:28) [1]Код библиотеки:
> library hToPr;
>
> uses
> Windows,
> Messages,
> SysUtils,
> tlHelp32,
> Classes;
>
> var
> Error:string;
>
> {$R *.res}
>
> function hGetLastError: PChar; stdcall;
> begin
> Result:=PChar(Error);
> end;
>
> ...
>
> exports
> hGetLastError, ...;
> begin
>
> end.
>
← →
Гаврила © (2006-03-30 18:30) [2]ощибка в том, что некая бииблиотечная функция, к вызову которой все сводится, неявно освободила память, на которую вернула ссылку
← →
Гаврила © (2006-03-30 18:30) [3]А, нет
тогда ошибка скорее всего в соглашении о вызовах
← →
han_malign © (2006-03-30 18:31) [4]эээ
@hFunc := GetProcAddress(DLL, "hGetLastError");
if Assigned(@hFunc) then Result:=hFunc....
- и как ты себе представляешь исполняемый код функции в виде ASCIIZ строки???
← →
NightLord © (2006-03-30 18:36) [5]try
@hFunc := GetProcAddress(DLL, "hGetLastError");
if Assigned(@hFunc) then Result:=hFunc else Result:="hToPr: не найдена искомая функция";
finally
FreeLibrary(DLL);
end;
Дак как ты можешь вызвать функцию из библиотеки если ты ее удалил из памяти?
← →
NightLord © (2006-03-30 18:38) [6]сорри невнимательно прочитал код библиотеки -(
← →
begin...end © (2006-03-30 18:40) [7]> han_malign © (30.03.06 18:31) [4]
Вы о чём?
← →
Хинт © (2006-03-30 18:41) [8]Совсем не понял смысла [4] и [5]
← →
begin...end © (2006-03-30 18:42) [9]> Хинт © (30.03.06 18:41) [8]
Главное, чтобы был понятен смысл [3].
← →
Rouse_ © (2006-03-30 18:43) [10]
> Вы о чём?
Вглядись внимательно в код :)
← →
Хинт © (2006-03-30 18:43) [11]Убрать stdcall? Можно немного подробнее
← →
Гаврила © (2006-03-30 18:44) [12]Кстати да
во первых - соглашение о вызовах
во вторых
Память то выделена внутри библиотеки
var
Error:string;
А мы ее выгрузили. А потом читаем по этому адресу.
Нехорошо
← →
begin...end © (2006-03-30 18:45) [13]> Rouse_ © (30.03.06 18:43) [10]
Вгляделся. И что?
← →
Хинт © (2006-03-30 18:45) [14]
> во первых - соглашение о вызовах
Убрать stdcall?
> var Error:string;А мы ее выгрузили. А потом читаем по этому
> адресу.
Т.е. в Result заносится адрес строки, а не сама строка?
← →
Rouse_ © (2006-03-30 18:47) [15]
> Вгляделся. И что?
Да какбы было бы интересно что делать с результатом...
← →
Гаврила © (2006-03-30 18:52) [16]
> Убрать stdcall?
с двух сторон должно быть одинаково - или и там и там есть
или и там и там нету
> .е. в Result заносится адрес строки, а не сама строка?
в Result заносится адрес первого символа строки
← →
begin...end © (2006-03-30 18:54) [17]Да, похоже, проблема в [12] (2), потому что соглашение о вызовах в данном случае роли не играет. Ввиду отсутствия параметров. Хотя вообще, конечно, правильно, чтобы и там, и там соглашения были одинаковыми.
> Rouse_ © (30.03.06 18:47) [15]
Использовать? :)
Я не совсем понял, в чём смысл [4]. Адрес функции получили, саму функцию вызвали. Что не так-то?
← →
Хинт © (2006-03-30 18:59) [18]Без FreeLibrary работает... Ошибка в Result:=hFunc.
Решение: заменить на Result:=PChar(Copy(hFunc,0,255))?
А как сообщить о соглашении в функции из [1]?
← →
Хинт © (2006-03-30 19:04) [19]Хм. Вот вызов другой функции:
function hCodeInject(PID: integer): boolean;
var
func: function(PID: integer): boolean;
LibHandle: THandle;
begin
Result := false;
@func := nil;
LibHandle := LoadLibrary(lname);
if LibHandle >= 32 then
begin
@func := GetProcAddress(LibHandle, "hCodeInject");
if @func <> nil then Result := func(PID);
end;
FreeLibrary(LibHandle);
end;
Опять же "Access violation at address...", хотя никаких PChar"ов тут уже нет
← →
Хинт © (2006-03-30 20:28) [20]Чудеса! Из-под IDE работает нормально, а отдельно без Delphi уже "Access violation at address..."
← →
Гаврила © (2006-03-30 23:25) [21]
> Без FreeLibrary работает...
> Опять же "Access violation at address...", хотя
> никаких PChar"ов тут уже нет
Проверь еще, может быть где-то косяк в самой библиотеке на финализации юнитов.
Хотя я почти уверен, что в примереfunc: function(PID: integer): boolean;
опять не соблюдено соглашение о вызовах
← →
Alexander Panov © (2006-03-31 00:04) [22]>Хинт
Возьми за правило - выделять, изменять размер, освобождать память в одном месте. Если выделяешь в основной программе, в ней же освобождать и изменять размер. то же самое с DLL.
Для обработки строк в DLL используй стандартный прием, принятый в WINAPI:
Выделяешь в основной программе память, передаешь указатель и длину(!) в DLL. В DLL обрабатываешь, не затрагивая распределение памяти. Далее в основной программе делаешь с памятью все, что угодно.function ProcessString(Str: PChar; LenStr: Integer): Integer; external "test.dll"; stdcall;
Первый вариант:
function Test(Str: PChar): String;
var
LenResult: Integer;
begin
GetMem(Str,500);
try
LenResult := ProcessString(Str,500);
SetLength(Result, LenResult);
Move(Str[0],Result[1],LenResult);
finally
FreeMem(Str);
end;
end;
Второй вариант:function Test(Str: String): String;
var
LenResult: Integer;
begin
Str := "1234567890";
LenResult := ProcessString(PChar(Str),Length(Str));
SetLength(Result, LenResult);
Result := Str;
end;
Функция в DLL:function ProcessString(Str: PChar; LenStr: Integer): Integer; stdcall;
var
s: String;
begin
s := String(Str);
if s[1]="1"
then s :="Test1"
else s :="Test2";
if Length(s)>LenStr then SetLength(s,LenStr);
FillChar(Str[0],LenStr,#0);
Move(s[1],Str[0],Length(s);
end;
Ну и третий вариант(если кроме Delphi, других языков не будет использоваться) - использовать специальные менеджеры памяти ShareMem или FastMem.
Страницы: 1 вся ветка
Текущий архив: 2006.04.23;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.026 c