Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 02.06.2015, 03:27
Аватар для Alloc
Alloc Alloc вне форума
Начинающий
 
Регистрация: 17.09.2014
Сообщения: 104
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию Как объявить процедуру из dll библиотеки?

Всем привет!

Ситуация такая. Объявил я процедуры таким образом:
Код:
1
2
3
4
5
6
procedure LoadSkin(lpszPath: String; lpszIniFileName: String);
stdcall; external 'isskin.dll';
 
// Importing UnloadSkin API from ISSkin.DLL
procedure UnloadSkin();
stdcall; external 'isskin.dll';

В ресурсах программы прячу dll - библиотеку. При создании формы она должна распаковываться в ТЕМП, ну а потом начинаю работать с библиотекой..

Вообщем проблема в том, что при запуски программы я получаю ошибку, что библиотека не найдена... если ее положить конечно в папку с программой тогда работает...

что можно сделать?
Ответить с цитированием
  #2  
Старый 02.06.2015, 04:55
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,093
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Загружать ее динамически через LoadLibrary. Статическая линковка так работать не будет - библиотека в таком случае должна быть доступна на момент загрузки приложения, т.к. при статической линковке за загрузку всех требуемых библиотек отвечает операционная система.
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Alloc (02.06.2015)
  #3  
Старый 02.06.2015, 12:29
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Да, только LoadLibrary, GetProcAddress и прочие танцы с бубном. Для особо упоротых существует код для ручной загрузки библиотеки прямо из оперативки, без сохранения на диск. Но лучше подобной фигнёй не заниматься - это плохая практика: во-первых, это неудобно, а во-вторых, передать программу в виде установщика/архива ничуть не сложнее, и при этом по системе не будут разбрасываться всякие сомнительные исполняемые файлы и загаживать место.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.

Последний раз редактировалось Bargest, 02.06.2015 в 12:45.
Ответить с цитированием
Этот пользователь сказал Спасибо Bargest за это полезное сообщение:
Alloc (02.06.2015)
  #4  
Старый 02.06.2015, 13:20
Аватар для Alloc
Alloc Alloc вне форума
Начинающий
 
Регистрация: 17.09.2014
Сообщения: 104
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Спасибо за ответы. Если не сложно, не могли бы вы предоставить небольшой пример как это происходит, для реализации поставленной задачи?

Т.е. библиотеку все равно придется распаковать и загрузить в память при помощи LoadLibrary(LibFileName: PChar)... может можно как то напрямую из ресурсов ее загрузить...? я немного не понимаю, объясните пожалуйста
Ответить с цитированием
  #5  
Старый 02.06.2015, 13:31
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

В LoadLibrary передается путь к библиотеке. Она возвращает описатель загруженной библиотеки (насколько я помню, это обычный указатель на ее начало в памяти). Потом через GetProcAddress с использованием этого указателя нужно найти все требуемые функции из DLL и сохранить в переменных типа "функция". Затем вызывать. Это неудобно, но работает.
Грузить прямо из памяти - это извращение, потому что это делается вручную. Код, который я видел - это фактически люди сами писали свой LoadLibrary и GetProcAddress. Сами анализируют таблицы импорта и экспорта библиотеки, применяют релокации и т.д.
Самый лучший выход - не заниматься всей этой фигнёй. Просто положить библиотеку рядом и всё. Если передаешь программу кому-то - собери в ZIP или в установщик и передавай его.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
Этот пользователь сказал Спасибо Bargest за это полезное сообщение:
Alloc (02.06.2015)
  #6  
Старый 02.06.2015, 13:58
Аватар для Alloc
Alloc Alloc вне форума
Начинающий
 
Регистрация: 17.09.2014
Сообщения: 104
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Скажите, вот допустим есть код:

Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
procedure TForm1.btn1Click(Sender: TObject);
type
  TLoadSkin = procedure(lpszPath: String; lpszIniFileName: String);
  var
    DLLInstance : THandle;
    LoadSkin : TLoadSkin;
begin
  DLLInstance := LoadLibrary('ISSkin.dll');
  if DLLInstance = 0 then
  begin
     MessageDlg('Невозможно загрузить DLL', mtError, [mbOK], 0);
     Exit;
  end;
  @LoadSkin := GetProcAddress(DLLInstance, 'LoadSkin');
  if @LoadSkin = nil then
     LoadSkin('Skin.cjstyles','')
  else
     MessageDlg('Не найдена искомая процедура.', mtError, [mbOK], 0);
  FreeLibrary(DLLInstance);
end;

выходит сообщение "Не найдена искомая процедура."

пожалуйста подскажите, что не так в коде? Заранее спасибо.
Ответить с цитированием
  #7  
Старый 02.06.2015, 14:24
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

А LoadSkin сам писал или ктото другой?
На чём написана?
Если на C/C++ то какой у неё LoadSkin.h
Если на Дельфи, то покажи, как экспортирубтся функции?
Или, используя TDump, покажи, какие функции экспортирует библиотека.
Ответить с цитированием
Этот пользователь сказал Спасибо icWasya за это полезное сообщение:
Alloc (02.06.2015)
  #8  
Старый 02.06.2015, 14:55
Аватар для Alloc
Alloc Alloc вне форума
Начинающий
 
Регистрация: 17.09.2014
Сообщения: 104
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от icWasya
А LoadSkin сам писал или ктото другой?

нет, я не автор. Вообще библиотека предназначена для известного инсталлятора Inno Setup в котором используется скриптовый язык точь-в-точь как Delphi. Библиотека просто устанавливает Скин приложению.

Для лучшего понимания я немного расскажу как оно работает..

В сам скрипт, в секцию [Files] добавляют два файла, саму библиотеку и скин.

Код:
1
2
3
4
5
6
7
[Files]
; Add the ISSkin DLL used for skinning Inno Setup installations.
Source: ISSkin.dll; DestDir: {app}; Flags: dontcopy
 
; Add the Visual Style resource contains resources used for skinning,
; you can also use Microsoft Visual Styles (*.msstyles) resources.
Source: Office2007.cjstyles; DestDir: {tmp}; Flags: dontcopy

хранится все это в екзешнике инсталлятора
имеет следующие функции:

Код:
1
2
3
4
5
6
7
8
[Code_]
// Importing LoadSkin API from ISSkin.DLL
procedure LoadSkin(lpszPath: String; lpszIniFileName: String);
external 'LoadSkin@files:isskin.dll stdcall';
 
// Importing UnloadSkin API from ISSkin.DLL
procedure UnloadSkin();
external 'UnloadSkin@files:isskin.dll stdcall';

вызывается при создании формы и при закрытии

Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function InitializeSetup(): Boolean;
begin
  ExtractTemporaryFile('Office2007.cjstyles');
  LoadSkin(ExpandConstant('{tmp}\Office2007.cjstyles'), '');
  Result := True;
end;
 
procedure DeinitializeSetup();
begin
  // Hide Window before unloading skin so user does not get
  // a glimpse of an unskinned window before it is closed.
  ShowWindow(StrToInt(ExpandConstant('{wizardhwnd}')), 0);
  UnloadSkin();
end;

Инсталлятор при старте выгружает библиотеку и скин в ТЕМП после чего видимо подключает ее и устанавливает скин... вот и я этого добиваюсь.

Пока что получилось только загружать скин при запуске программы и выгружать при закрытии. При условии, что dll-библиотека лежит в папке с программой ..

Проще говоря, пытаюсь сделать следующее:
1.Dll - библиотека должна хранится в ресурсах программы вместе со Скином.
2.При запуске - распаковывать или загружать в память dll - библиотеку... в силу своего небольшого опыта в программировании я не знаю как лучше сделать...
3.Загружать Скин используя функцию из библиотеки
4.Выгружать из памяти\удалять при закрытии формы.


Я буду очень благодарен если поможете мне осуществить задуманное, ведь очень удобно иметь возможность в любое время сменить внешний вид программы.

Последний раз редактировалось Alloc, 02.06.2015 в 15:12.
Ответить с цитированием
  #9  
Старый 02.06.2015, 22:38
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,093
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Да просто очепятка там в коде. Как раз в случае успешного нахождения функции показывается сообщ. об ошибке.
Твой код:
Код:
1
2
3
4
5
6
@LoadSkin := GetProcAddress(DLLInstance, 'LoadSkin');
  if @LoadSkin = nil then
     LoadSkin('Skin.cjstyles','')
  else
     MessageDlg('Не найдена искомая процедура.', mtError, [mbOK], 0);
  FreeLibrary(DLLInstance);

Надо:
Код:
1
2
3
4
5
6
@LoadSkin := GetProcAddress(DLLInstance, 'LoadSkin');
  if @LoadSkin = nil then
     MessageDlg('Не найдена искомая процедура.', mtError, [mbOK], 0)
  else
     LoadSkin('Skin.cjstyles','');
  FreeLibrary(DLLInstance);

PS. Ну или оператор сравнения в if поменять.
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Alloc (02.06.2015)
  #10  
Старый 02.06.2015, 22:49
Аватар для Alloc
Alloc Alloc вне форума
Начинающий
 
Регистрация: 17.09.2014
Сообщения: 104
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

спасибо. странно, но если я ставлю в событие FormCreate то скин почему то не загружается... а вот если поставить код в сам Project.dpr до инициализации приложения тогда срабатывает.. но после закрытия приложения вылетает куча ошибок со ссылкой на разные библиотеки...
Ответить с цитированием
  #11  
Старый 02.06.2015, 23:17
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,093
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Это надо отдельно разбираться.
Видимо, скин должен быть загружен на момент инициализации приложения (возможно, хакают создание форм; дело в том, что в момент OnCreate, само окно уже создано).
По поводу ошибок с ссылками на разные библиотеки - надо смотреть что за ошибки и откуда ноги растут. Ну и проверить запуск не из IDE, может просто там действительно куча разных исключений, но они отлавливаются внутри кода и наружу не выходят.
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Alloc (02.06.2015)
  #12  
Старый 02.06.2015, 23:38
Аватар для Alloc
Alloc Alloc вне форума
Начинающий
 
Регистрация: 17.09.2014
Сообщения: 104
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Слишком все это сложно оказалось)) В любом случае большое спасибо lmikle за помощь и всем остальным тоже огромное спасибо! Пойду тогда по другому пути.. жаль, вроде бы такая мелочь - а столько геморроя))
Ответить с цитированием
  #13  
Старый 03.06.2015, 12:39
Аватар для Alloc
Alloc Alloc вне форума
Начинающий
 
Регистрация: 17.09.2014
Сообщения: 104
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Скажите, а как вы смотрите на то, чтобы написать отдельно программу которая будет распаковывать в ТЕМП основную программу с библиотекой и скином и запускать ее оттуда? Потом удалять все это естественно... и так каждый раз. на сколько это разумно?) Так делают?

заранее спасибо
Ответить с цитированием
  #14  
Старый 03.06.2015, 15:13
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

*хлебный троллейбус.жпг*
Делают. Тот же винрар позволяет распаковать во временнуюипапку и запустить оттуда программу. Потом всё потрёт. SFX-архив.
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
Этот пользователь сказал Спасибо M.A.D.M.A.N. за это полезное сообщение:
Alloc (03.06.2015)
  #15  
Старый 03.06.2015, 15:28
Аватар для Alloc
Alloc Alloc вне форума
Начинающий
 
Регистрация: 17.09.2014
Сообщения: 104
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Благодарю)
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 03:58.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025