C++Builder
Начало
Форум
Помощь
Войти
Регистрация
C++Builder
>
Forum
>
Вопросы программирования
>
Общие вопросы программирования в C++Builder
>
Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений
Страниц: 1 [
2
]
Вниз
Печать
Автор
Тема: Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений (Прочитано 33929 раз)
AVC
Администратор
Сказали спасибо: +28/-6
Offline
Сообщений: 1189
Re: Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений
«
Ответ #30 :
09 Ноябрь 2007, 12:33:37 »
Т.е. вы согласны таскать свои а Борланд пусть "обломится"?
Я думаю, что можно сделать вариант, когда все необходимое включено в один из своих модулей, а все остальные надстройки, в том числе и сам exe'шник ссылается на эту кучу. Но эта ручная гемморная работа, которую, с моей точки зрения, можно легко заменить просто тасканием борландовских bpl'й. Особенно в условиях, когда критится более одного приложения с этими пакетами.
Записан
oxotnik
Глобальный модератор
Сказали спасибо: +100/-15
Offline
Сообщений: 2425
Re: Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений
«
Ответ #31 :
09 Ноябрь 2007, 14:07:25 »
я же не таскаю за собой *.срр и *.hpp... и прочие *.obj (а они для проекта ой как нужны)
так почему нельзя сделать что бы и bpl не приклеивались (это вопрос скорей к борланду)
Записан
oxotnik
Глобальный модератор
Сказали спасибо: +100/-15
Offline
Сообщений: 2425
Re: Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений
«
Ответ #32 :
17 Декабрь 2007, 10:00:18 »
поясните плз:
почему в длл
Код:
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
выполняется не при FreeLibrary(...) а при закрытии основного приложения ?!
Записан
Termi_uc
Давний друг
Сказали спасибо: +1/-0
Offline
Сообщений: 86
Re: Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений
«
Ответ #33 :
18 Декабрь 2007, 11:24:03 »
Цитата: oxotnik от 09 Ноябрь 2007, 14:07:25
я же не таскаю за собой *.срр и *.hpp... и прочие *.obj (а они для проекта ой как нужны)
...
Для проекта конечно нужны, а вот для работы приложения - нет.
Цитата: oxotnik от 09 Ноябрь 2007, 14:07:25
...
так почему нельзя сделать что бы и bpl не приклеивались (это вопрос скорей к борланду)
Это ты сам решаешь - приклеивать их или нет. Просто иногда лучше разделять приложение на исполняемый модуль и набор библиотек (BPL - это та же библиотека DLL, только с некоторыми функциями "По-умолчанию").
Цитата: oxotnik от 17 Декабрь 2007, 10:00:18
поясните плз:
почему в длл
Код:
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
выполняется не при FreeLibrary(...) а при закрытии основного приложения ?!
Ошибка в коде?
Воспользуйся этом простым кодом для того, чтобы посмотреть работает твой вызов FreeLibrary или нет.
Код:
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
switch(reason)
{
case DLL_PROCESS_ATTACH:
ShowMessage("DLL_PROCESS_ATTACH");
break;
case DLL_THREAD_ATTACH:
ShowMessage("DLL_THREAD_ATTACH");
break;
case DLL_THREAD_DETACH:
ShowMessage("DLL_THREAD_DETACH");
break;
case DLL_PROCESS_DETACH:
ShowMessage("DLL_PROCESS_DETACH");
break;
}
return 1;
}
(или просто Break Point в отладчике)
Записан
oxotnik
Глобальный модератор
Сказали спасибо: +100/-15
Offline
Сообщений: 2425
Re: Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений
«
Ответ #34 :
18 Декабрь 2007, 11:38:24 »
Цитировать
(или просто Break Point в отладчике)
как раз бейкпоитном и узнал, что после FreeLibrary на момент закрытия приложения (библиотека давно и успешно была выгружена) вызвается ф-я инициализации длл... с какго фига то???
Записан
Termi_uc
Давний друг
Сказали спасибо: +1/-0
Offline
Сообщений: 86
Re: Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений
«
Ответ #35 :
18 Декабрь 2007, 12:33:01 »
Я не понимаю, ты же говоришь, что библиотека бавно выгружена - тогда как может вызыватся ЕЁ функция?
Повторюсь: Может ошибка в коде?
Проверь можешь ты удалить/переместить твою библиотеку, когда ты
думаешь
, что она выгружена.
Вообще DllEntryPoint не вызывается автоматически, если ты загрузил DLL динамически и забыл выгрузить и закрываешь свою прогу. Проверено опытным путем .
Записан
oxotnik
Глобальный модератор
Сказали спасибо: +100/-15
Offline
Сообщений: 2425
Re: Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений
«
Ответ #36 :
18 Декабрь 2007, 13:48:13 »
Цитата: Termi_uc от 18 Декабрь 2007, 12:33:01
Я не понимаю, ты же говоришь, что библиотека бавно выгружена - тогда как может вызыватся ЕЁ функция?
Повторюсь: Может ошибка в коде?
Проверь можешь ты удалить/переместить твою библиотеку, когда ты
думаешь
, что она выгружена.
Вообще DllEntryPoint не вызывается автоматически, если ты загрузил DLL динамически и забыл выгрузить и закрываешь свою прогу. Проверено опытным путем .
в том то и весь вопрос: какого ... вызвывется DllEntryPoint, если библиотека выгружена ?
ЗЫ: Проверял в пошаговом режиме.
ЗЫЗЫ: Загружаю и выгружаю один раз
ЗЫЗЫЗЫ: Проверкой на удаление ничего не добъешься, т.к. система не сразу "отпускает" файл dll
«
Последнее редактирование: 18 Декабрь 2007, 14:07:04 от oxotnik
»
Записан
AVC
Администратор
Сказали спасибо: +28/-6
Offline
Сообщений: 1189
Re: Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений
«
Ответ #37 :
18 Декабрь 2007, 17:18:57 »
Давно использую, ни разу на такие грабли не наступал при выполнении условия - что сам грузил, сам и выгружай, что грузил борланд (упоминалось в build with runtime.. или еще где-то) не трогать - сам выгрузит.
PS. к сведению, вдруг да поможет
Еще у 5-ки есть такая особенность: если в рамках основного приложения вручную создан модуль данных, то разрушать его не надо - приложение это сделает само или будет "стучать ногами"
PPS. Вот код (работающий кусок), который показывает загруженные в настоящий момент библиотеки
Код:
//---------------------------------------------------------------------------
//
Получить список загруженных модулей (exe, bpl, dll)
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TStringList
*lst = (TStringList*)Memo1->Lines;
lst->Clear();
char buf [255];
TLibModule *lbm;
AnsiString fname, sname, path, drv, dir, name, ext;
for (lbm = LibModuleList; lbm; lbm = lbm->next)
{ GetModuleFileName((HMODULE)lbm->instance, buf, 254);
fname = AnsiString(buf).Trim().UpperCase();
if (!fname.IsEmpty()) lst->Add(AnsiString(int(lbm->instance)) + ": " + fname);
}
Записан
oxotnik
Глобальный модератор
Сказали спасибо: +100/-15
Offline
Сообщений: 2425
Re: Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений
«
Ответ #38 :
25 Декабрь 2007, 17:39:26 »
Еще одна проблема назрела:
Передаю в a-ю длл TObject *Sender
в самой длл:
TComboBox *cmb = dynamic_cast
(Sender);
никак не хочет работать (cmb = NULL)
а вот так:
TComboBox *cmb = (TComboBox *) Sender;
работает
Что за грабли?
Записан
AVC
Администратор
Сказали спасибо: +28/-6
Offline
Сообщений: 1189
Re: Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений
«
Ответ #39 :
25 Декабрь 2007, 17:55:42 »
Возможно где-то указатель был приведен просто к void* или int или чему еще достаточно простому.
Записан
oxotnik
Глобальный модератор
Сказали спасибо: +100/-15
Offline
Сообщений: 2425
Re: Фундаментальные основы DLL/VCL плагинов. Несколько вопросов и соображений
«
Ответ #40 :
25 Декабрь 2007, 20:00:58 »
Цитата: AVC от 25 Декабрь 2007, 17:55:42
Возможно где-то указатель был приведен просто к void* или int или чему еще достаточно простому.
нет, как получаю в функции-событии так же и передаю:
Код:
void __fastcall TForm1::BtnOnClick (TObject *Sender)
{
...
FuncFromDLL(Sender);
....
}
Записан
olegenty
Администратор
Сказали спасибо: +16/-7
Offline
Сообщений: 520
Re: Фундаментальные основы DLL/VCL плагинов. Неско&
«
Ответ #41 :
01 Октябрь 2008, 14:50:27 »
Мой вариант - отдельная библиотека.
1. Есть некий класс-адаптер, с определенным интерфейсом регистрируемых в нем функций.
Код:
////////////////////////////////////////////////////////////////////////////
//
// Тип-указатель на некую адаптерную функцию со вполне конкретным типом
// аргумента и результатом
//
typedef boost::function1
TFuncType;
////////////////////////////////////////////////////////////////////////////
//
// Тип функции
//
typedef enum TFuncKind {
fkNull = 0 // Нифига нет, указатель тупо указывает в небо
, fkExecutable = 1 // Функция, реализованная в EXE
, fkExport = 2 // Функция, реализованная в DLL и экспортируемая оттуда
, fkService = 3 // Сервисная функция (живет в течение жизни модуля, где зарегистрирована)
} TFuncKind;
////////////////////////////////////////////////////////////////////////////
//
// Класс, инкапсулирующий функцию.
//
class PACKAGE CFunc
{
public:
CFunc();
CFunc(const CFunc&);
CFunc(TFuncKind Kind, TFuncType Func);
TFuncKind const Kind();
TFuncType const Func();
private:
TFuncKind Kind_;
TFuncType Func_;
};
////////////////////////////////////////////////////////////////////////////
//
// Шаблон будущего адаптера
//
class PACKAGE CAdapter: public OInstanceLocker
{
public:
typedef CFunc FuncType;
typedef map
FuncsType;
typedef FuncsType::size_type SizeType;
bool Exists(const AnsiString Name);
bool Register(const AnsiString Name, const TFuncKind Kind, const TFuncType Func);
bool Unregister(const AnsiString Name);
virtual TFuncType::result_type operator()(const AnsiString Name, TFuncType::argument_type);
SizeType Count();
protected:
FuncType& operator[](AnsiString Index);
private:
FuncsType Funcs_;
FuncType NullFunc_;
};
Функции регистрируются там так:
Код:
extern "C" __declspec (dllexport) bool __stdcall Register(OTCAdapter::CAdapter* const Adapter)
{
try
{
Adapter->Register("Task.Set" , OAdapter::fkExport, boost::bind<:prestable>(TaskSet , Adapter, _1));
Adapter->Register("Task.Default" , OAdapter::fkExport, boost::bind<:prestable>(TaskDefault , Adapter, _1));
Adapter->Register("Task.Examine" , OAdapter::fkExport, boost::bind<:prestable>(TaskExamine , Adapter, _1));
Adapter->Register("Task.MessageExamine" , OAdapter::fkExport, boost::bind<:prestable>(TaskMessageExamine , Adapter, _1));
Adapter->Register("Task.Cancel" , OAdapter::fkExport, boost::bind<:prestable>(TaskCancel , Adapter, _1));
Adapter->Register("Task.Pass" , OAdapter::fkExport, boost::bind<:prestable>(TaskPass , Adapter, _1));
Adapter->Register("Task.Drop" , OAdapter::fkExport, boost::bind<:prestable>(TaskDrop , Adapter, _1));
Adapter->Register("Task.Start" , OAdapter::fkExport, boost::bind<:prestable>(TaskStart , Adapter, _1));
Adapter->Register("Task.Finish" , OAdapter::fkExport, boost::bind<:prestable>(TaskFinish , Adapter, _1));
Adapter->Register("Task.ChangePlanFinish" , OAdapter::fkExport, boost::bind<:prestable>(TaskChangePlanFinish , Adapter, _1));
Adapter->Register("Task.View" , OAdapter::fkExport, boost::bind<:prestable>(TaskView , Adapter, _1));
Adapter->Register("Task.Message" , OAdapter::fkExport, boost::bind<:prestable>(TaskMessage , Adapter, _1));
Adapter->Register("Task.PlanFinishChangeRequest", OAdapter::fkExport, boost::bind<:prestable>(TaskPlanFinishChangeRequest, Adapter, _1));
Adapter->Register("Task.PlanFinishChangeAccept" , OAdapter::fkExport, boost::bind<:prestable>(TaskPlanFinishChangeAccept , Adapter, _1));
return true;
} catch (const Exception &E)
{
OUtils::CatchExceptionMessage("Ошибка регистрации функций модуля Task.dll", E);
}
return false;
}
или так:
Код:
Adapter_->Register("Main.Connection" , OAdapter::fkExecutable, boost::bind(&Tfm::Conn , this, _1));
Adapter_->Register("Main.MainForm" , OAdapter::fkExecutable, boost::bind(&Tfm::MainForm , this, _1));
Adapter_->Register("Main.FunctionModule", OAdapter::fkExecutable, boost::bind(&Tfm::DLLByFuncName , this, _1));
Adapter_->Register("Main.LoadModule" , OAdapter::fkExecutable, boost::bind(&Tfm::LoadFunctionUnit, this, _1));
Adapter_->Register("Main.ActionCID" , OAdapter::fkExecutable, boost::bind(&Tfm::ActionCID , this, _1));
Интерфейс функции известен. Где бы она ни была реализована, после регистрации она доступна из любого места.
На этом механизме разработан набор классов: CPlugins, CModules, CPlugin, CModule...
CModule - загружаемый модуль.
CPlugin - плагин, наследник формы (пока):
Код:
class PACKAGE CPlugin: public TForm
{
friend class CPlugins;
public:
typedef CAdapter AdapterClass;
__fastcall CPlugin(AdapterClass* const Adapter, PTable Params);
void __fastcall Close();
__property AdapterClass* const Adapter = {read = Adapter_};
__property AnsiString Title = {read = Title_};
protected:
AdapterClass* const Adapter_ ;
bool Initiated_;
AnsiString Title_ ;
CFileVersion Version_ ;
bool Register_ ;
bool SetSize_ ;
PTable Params_ ;
private:
virtual void __fastcall InitComplete() = 0;
virtual void __fastcall WndProc(Messages::TMessage &Message);
virtual void __fastcall OnInitComplete(Messages::TMessage &Message);
};
для Plugin пишется DLL, в ней:
Код:
//---------------------------------------------------------------------------
extern "C" __declspec (dllexport) OTCPlugin::CPlugin* __stdcall Execute(OTCAdapter::CAdapter* const Adapter, const AnsiString PluginName, PTable Params)
{
if (PluginName == "MyTasks")
{
return new TfmMyTasks(Adapter, Params);
} else
{
OUtils::Exclamation("MyTasks.dll: не найден плагин \"MyTasks\"");
}
return NULL;
}
//---------------------------------------------------------------------------
extern "C" __declspec (dllexport) void __stdcall Free(CPlugin* Form)
{
delete Form;
}
в целом - всё работает. Плагинность + адаптируемость всех атомарных функций даёт возможность легко сопровождаемой разработки.
Всё это
Build with runtime packages + Use dynamic RTL
«
Последнее редактирование: 08 Октябрь 2008, 09:18:04 от olegenty
»
Записан
Страниц: 1 [
2
]
Вверх
Печать
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Вопросы программирования
-----------------------------
=> Общие вопросы программирования в C++Builder
=> Программирование с FMX
=> Работа с базами данных в C++Builder
=> Windows API
=> Технологии COM/DCOM, ActiveX
=> Аспекты и идеология профессиональной разработки ПО
=> Компьютерное железо и системное администрирование
=> студенческий городок
-----------------------------
Обсуждение материалов на сайте
-----------------------------
=> Обсуждений статей на сайте
=> Обсуждение материалов из файлового архива
=> Компоненты сторонних разработчиков к С++Builder
-----------------------------
Работа сайта и новости
-----------------------------
=> Ищу/предлагаю работу
=> Новости из мира программирования
=> Новости - события календаря
=> Голосования
=> Компьютерный юмор и приколы
=> Работа сайта
=> Флейм
-----------------------------
FAQ - частозадаваемые вопросы/ответы
-----------------------------
=> FAQ, общие вопросы, посвящённые C++Builder
=> FAQ, вопросы по базам данных
=> FAQ, вопросы по компонентам
Загружается...