Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Своя программа и плагин к ней 
:(
    Опции темы
mr.Anderson
Дата 13.6.2007, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


Профиль
Группа: Участник Клуба
Сообщений: 3374
Регистрация: 20.12.2004
Где: далеко

Репутация: 3
Всего: 128



Порыл Google, но не смог найти толковой информации по этому поводу. Как мне к собственной программе создать плагин? Каков вообще принцип построения плагинов? Что для чтения плагина должно быть в моей расширяемой программе? Прошу помочь либо подробными разъяснениями, либо статейками (крайне желательно на русском языке).


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Klin
Дата 13.6.2007, 23:46 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1938
Регистрация: 7.10.2002
Где: Краснодар

Репутация: 20
Всего: 25



Попробую на русском smile

mr.Anderson, есть разные подходы,  в зависимости от того, какую цель вы преследуете. Плагины - всегда вещь полезная (хотя не рекомендую при создании калькуляторов). Плюсы их использования на лицо. Каждый из них отвечает за определенную часть программы, соответственно при нахождении недочетов, усовершенствовании и т.п. заменяется не сама программа, а только чать ее. Также с оперативка вам только спасибо скажет если, вы будите грузить не 100 метров, а только нужные в данный момент 5.  
Обычно это DLL файл, в нем  может быть че угодно. Будь то коллекция изображений для дизайна, тексты для перевода программы или формы, диалоги, меню и прочее. Способы создания тоже не мало. К примеру можно создать DLL (Файл->Новый->Мастер DLL). Затем создать в этом проекте новую форму (или фрейм). Будет необходимо прописать что-то типа: 

Код

extern "C" void  __declspec(dllexport) OpenModule(TForm* Owner)
{
      static TForm2* form = new TForm2(Owner);

}


Ну то, что форму нужно прописать не напоминаю smile Это будет простейший плагин. На форме может быть что угодно. Теперь необходимо написать, так называемое хост приложение. Не важно, что будет в нем, но главное чтобы был вызов нашего модуля (или плагина как кому нравиться smile ) Расскажу-ка я про динамическую загрузку smile Должны произойти следующие действия:
  •  Загрузка модуля в память
  •  Использование возможностей модуля
  •  Его закрытие
Вот это и есть залог успеха. В моем примере - выведем нашу форму на экран:

Код

Dll_name = "C:\\Project1.dll";
if (HINSTANCE Dll_adress = LoadLibrary(Dll_name))
  {
     typedef TForm* (__cdecl* TCreateMyForm)(TForm*);
     if( TCreateMyForm CreateMyForm = (TCreateMyForm)GetProcAddress(Dll_adress,"_OpenModule")) {
      form = CreateMyForm(this); 
      /* дальнейшие действия */
    }
  }  


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

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

Код

 #pragma resource "Project1.dll"


Но здесь имхо больше минусов:
  •  Захотите обновить ваш плагин - придется работать с ресурсами программы, а не просто заменить нужный файл
  •  Сама программа прибавляется в весе, т.е изменяется программа и тащит все старые модули на себе.
  •  Почти отсутствует возможность догрузки плагина
Хотя есть один плюс - простота в использовании. Вообще писать могу много, но ночи слишком короткие smile А преподы утром злые  smile . Возникнут вопросы - пиши.

Добавлено через 8 минут и 46 секунд
так зарисовочка плагинов smile

user posted image
Динамика

user posted image
Статика



--------------------
Я человек - попробуйте обвинить меня за это.
PM MAIL   Вверх
jonie
Дата 14.6.2007, 00:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 7
Всего: 118



пишешь длл-ку спец вида (спец вид определяешь ТЫ : например условие - наличие функции Init())
а далее грузишь ее динамически через LoadLibrary  (поищи по форуму, тут не раз эта тема появлялась)....
т.о. имеем:
директорию с плагинами, в ней перебираем все длл-ки, и смотрим наличие у них экспортной функции (ну или еще чего что сам опреялешь), а далее остается только передавать данные в\из плагина... Как это реализовать тож было... например передавать указатели, или функторы....
---------
реальный пример (урощенно):
есть прога проверяющая балланс счета. Суть плагинов - вызывается спец функция MainPluginFunction() в них (при каждой проверке), которой передаются данные о баллансе (через указатель на структуру).

Программа грузит динамически плагины  при старте:
Код

#define PLUGIN_EXT "*.dll"
......
CPluginList::CPluginList(string strPluginDir)
{
    bool ErrorDetected=false;
    char buf[MAX_PATH+256];    //под всякие пути
    PLUGIN plugstruct;  //струкрута содержит HMODULE - hInstanse длл-ки загруженной, и данные о функторах (функций из плагина типа GetPlugName(), MainPluginFunction()..... 
    string ErrorMessage("Следующие плагины не могут быть загружены:\n");
    if(strPluginDir[strPluginDir.length()-1]!='\\')    strPluginDir.append("\\");
    //strPluginDir.append(PLUGIN_EXT);
    StringCchPrintf(buf,sizeof(buf),"%s%s",strPluginDir.c_str(),PLUGIN_EXT);
    WIN32_FIND_DATA finddata;
    HANDLE hFind = FindFirstFile(buf,&finddata);
    if(hFind!=INVALID_HANDLE_VALUE){
        do{
            //This File (if Find) cant be == "." OR ".." !
            //if( strcmp(finddata.cFileName,".") && strcmp(finddata.cFileName,"..") ){
                ZeroMemory(&plugstruct,sizeof(PLUGIN));
                StringCchPrintf(buf,sizeof(buf),"%s%s",strPluginDir.c_str(),finddata.cFileName);
                PLUGIN_RET_CODES retVal = LoadPlugin(buf,&plugstruct);   //в LoadPlugin() грузим DLL, заносим ее HMODULE  в структуру и заполняем поля структуры функуторами по GetProcAddress()
                if(retVal!=ALL_OK){
                    StringCchPrintf(buf,sizeof(buf),"DLL : %s (CODE=%d)\n",finddata.cFileName,retVal);
                    ErrorMessage.append(buf);
                    ErrorDetected = true;
                }
                else{
                    this->pluglist.push_back(plugstruct);  //сохраняем данные о плагине в векторе
                }
            //}
        }while(FindNextFile(hFind,&finddata));
    }
    FindClose(hFind);
    if(ErrorDetected) throw ErrorMessage;  //вызываем Exception если были найдены ошибки (но я не прерываю программу при первой ошибке, может загрузить хоть часть плагинов)
}


а далее в осной программе вызываем MainPluginFunction()  для каждого плагина, перебирая наш вектор....
Код

CPluginList* lpPlugList;
......
//тут инициализация (код выше)
....
//а тут наступает момент вызова плугов....
            for(std::vector<PLUGIN>::const_iterator i=lpPlugList->pluglist.begin();i!=lpPlugList->pluglist.end();i++){
                i->MainPluginFunction()
            }//end run plugins
....
//и продолжаем прогу


ессно не забываем про ошибки, threads и прочее...
но суть везде одна...

это простенький и сильно облегченный пример.. но думаю понять хватит....
---
как вариант можно юзать COM.......... но это более сложная песня имхо....



--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
mr.Anderson
Дата 14.6.2007, 12:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


Профиль
Группа: Участник Клуба
Сообщений: 3374
Регистрация: 20.12.2004
Где: далеко

Репутация: 3
Всего: 128



Объясните, пожалуйста, сверхподробно вот эти строчки:
Код

 typedef TForm* (__cdecl* TCreateMyForm)(TForm*);
     if( TCreateMyForm CreateMyForm = (TCreateMyForm)GetProcAddress(Dll_adress,"_OpenModule")) {


Это сообщение отредактировал(а) mr.Anderson - 14.6.2007, 12:30


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
jonie
Дата 14.6.2007, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 7
Всего: 118



Код

 typedef TForm* (__cdecl* TCreateMyForm)(TForm*);
определение функтора (указателя на функцию) , которая принимает указатель на экземпляр формы TForm  и возращает указатель на экземпляр TForm.
Код

  if( TCreateMyForm CreateMyForm = (TCreateMyForm)GetProcAddress(Dll_adress,"_OpenModule")) {
а это получение адреса такой функции из DLL.
Как она может ее реализовать (функцию такую в ДЛЛ)?
ну например 
Код

class TMyForm : public TForm{
 TForm* parentForm;  //указатель на форму родителя, например
....
}
....
 TForm* __cdecl _OpenModule(TForm* parentForm){
  return new TMyForm(parentForm);
.....
}

ну и экспорт не забыть.


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0487 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.