![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Ошибка при получение данных из dll [D5]
Учусь © (2011-04-10 21:56:00)Есть несколько дллок с ресурсами. Имена у них: res1.dll, res2.dll... Подключаю их и получаю из них названия ресурсов так:
procedure my15dll;
var i: Byte;
begin
FreeLibrary(hcDll);
for i := 0 to 15 do
begin
@procLoadCard := nil; hcDll := LoadLibrary(PChar('res'+IntToStr(i)+'.dll'));
if hcDll > HINSTANCE_ERROR then
begin
try
@procLoadCard := GetProcAddress(hcDll, 'nameres');
if @procLoadCard <> nil then nam := procLoadCard;
If (Form2.ComboBox2.Text<>StrPas(nam))and(Form2.ComboBox2.Items.IndexOf(StrPas(nam) )<0) then
Form2.ComboBox2.Items.Add(StrPas(nam));
except
end;
end;
FreeLibrary(hcDll);
end;
end;
Так работает, комбобокс заполняется, все ок, НО только если программа запущена из среды, по F9. Если запустить просто из ОС, то виснет на этой процедуре и Win7 ее закрывает, пишет: "программа не отвечает".
Помогите, похоже я тут что-то не то накрутил, подскажите, где что не так?
D5 W7
_Юрий (2011-04-18 19:58:00) [1]
> DiamondShark © (18.04.11 12:09) [10]
>
>
Я ж говорю - ошибка в соглашении о вызовах :-)
в библиотеке stdcall, который не указан при вызове
DiamondShark (2011-04-18 12:09:00) [2]
> Ну в общем, помогли найти вариант, при котором ошибка не
> проявляется.
Причём, ошибка была стопудово не в том, что описано.
Но разве знахарей это волнует?
_Юрий (2011-04-16 10:25:00) [3]Ну в общем, помогли найти вариант, при котором ошибка не проявляется.
Все довольны.
Это Прекрасно
_Юрий (2011-04-12 19:32:00) [4]Не нужно еще раз выделять память, если возвращается константа. Память под нее уже выделена. Лучше разобраться с соглашениями о вызовах, в библиотеке stdcall а в хосте что?
clickmaker (2011-04-12 13:47:00) [5]> [6] DiamondShark © (12.04.11 13:15)
предполагается, что если у чела ник "Учусь", то кроме как с константами ему иметь дело рановато?
DiamondShark (2011-04-12 13:15:00) [6]
> clickmaker © (11.04.11 13:00) [4]
Что это, Бэрримор?
> SetLength(nams, MaxLen);
> procLoadCard(PChar(names), MaxLen);
И получить в результате хвост из мусора, если nameres скопировала меньше символов, чем MaxLen.
Зачем такие сложности при возврате константы?
Учусь (2011-04-11 15:29:00) [7]
> clickmaker © (11.04.11 13:00) [4]
Премного благодарен. Разобрался с Вашей помощью:)
На правильном коде проще понять где грабли и как что работает.
clickmaker (2011-04-11 13:00:00) [8]вариант 1
procedure nameres(buf: PChar; MaxLen: integer); stdcall;
begin
StrLCopy(buf, ResName, MaxLen);
end;
usage:
SetLength(nams, MaxLen);
procLoadCard(PChar(names), MaxLen);
вариант 2
function nameres: PChar; stdcall;
begin
Result := PChar(LocalAlloc(LPTR, Length(ResName)+1);
StrCopy(Result, ResName);
end;
usage:
ResName := procLoadCard;
...
LocalFree(ResName);
Учусь (2011-04-11 12:45:00) [9]В dll функция возвращает строку - название хранящегося в ней ресурса:
function nameres : PChar; stdcall;
begin
Result := 'Resouce 1';
end;
exports
nameres;
{$R *.RES}
{$R res.res}
begin
end.
Код заполнения Комбобокса изменил так:
var
nams : String;
nam : PChar;
procLoadCard : function : PChar;
@procLoadCard := nil;
hcDll := LoadLibrary(PChar('res1.dll'));
if hcDll > HINSTANCE_ERROR then
begin
@procLoadCard := GetProcAddress(hcDll, 'nameres');
if @procLoadCard <> nil then nams := StrPas(procLoadCard);
If (Form2.ComboBox2.Text<>nams)and(Form2.ComboBox2.Items.IndexOf(nams)<0) then
Form2.ComboBox2.Items.Add(nams); FreeLibrary(hcDll);
end;
Но все равно виснет.. Не пойму где ошибка. Как сделать чтобы попроще?
_Юрий (2011-04-10 23:28:00) [10]
> except
> end;
так делать не надо - сокрытие ошибки только добавляет головной боли.
> FreeLibrary(hcDll);
вызывается даже в случае, если загрузка прошла неуспешно. Нехорошо.
Нужен код библиотечных функций.
Очень похоже на возврат PChar от локальной строки.
clickmaker (2011-04-10 22:10:00) [11]во-первых, зачем несколько раз StrPas(nam)?
потом, зачем FreeLibrary(hcDll) вначале?
что возвращает procLoadCard? PChar, судя по всему? откуда она эту строку берет?
LoadLibrary при ошибке возвращает NULL (0). Ошибку можно получить из GetLastError или SysErrorMessage(GetLastError)