Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2006.04.23;
Скачать: [xml.tar.bz2];

Вниз

Не пойму где ошибка (вызов функции из 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.012 c
6-1136885549
GuAV
2006-01-10 12:32
2006.04.23
Вопрос по Demos Internet NetChat


2-1143556598
коробас
2006-03-28 18:36
2006.04.23
Строки


3-1140767621
Bee-Bee
2006-02-24 10:53
2006.04.23
Летит база от ShotDown, глюк сортировки, неверная сортировка


3-1141208401
nap<>
2006-03-01 13:20
2006.04.23
DBLoockupComboBoxEh


4-1138865158
Aragon
2006-02-02 10:25
2006.04.23
Создание баллона





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский