Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.80/154: Рейтинг темы: голосов - 154, средняя оценка - 4.80
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
1

Теория плагинов

30.04.2010, 17:02. Показов 31701. Ответов 40
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет.
Для одной моей проги, нужно реализовать поддержку плагинов.
Плагины предполагаются простенькие, написанные на Си.

То, что плагин, это просто .so файл - понятно.
То, что прога может дергать из .so файла функции - тоже понятно.

1. Непонятно то, как сам плагин сможет дергать функции из программы?
2. Программа написана на С++, но плагины предполагаю писать на Си, во избежания бинарной несовместимости. В этом случае, какие сложности могут возникнуть?
3. Еще непонятно, каким образом "разделять" плагины, ведь их может быть несколько?
4. И еще непонятно, каким образом программе "сообщить" какие функции дергать из конкретного плагина?
5. И еще непонятно, каким образом плагин, сможет дергать функции из другого плагина?

Нужна теоретическая подкова

Благодарен всем откликнувшимся.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.04.2010, 17:02
Ответы с готовыми решениями:

Написание плагинов для notepad++
Добрый день! Есть задача написания плагина для notepad++ - немного модифицировать его графический...

Система плагинов
Добрый день форумчане. У меня к вам есть вопрос. Кратко. Как можно реализовать систему плагинов?...

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

Подключение плагинов к программе
Появилась необходимость в разработке текстового редактора с возможностью подключения своих...

40
22 / 22 / 2
Регистрация: 06.12.2010
Сообщений: 125
12.03.2011, 19:48 21
Author24 — интернет-сервис помощи студентам
эхх... чем пояснять и доказывать, вот вам пример:
Я тут обнаружила потребность народа в некотором примере насчёт использования динамических библиотек.
Вот, вытащила из своего проекта куски, относящиеся к загрузке и вызовам.
Смысл примера такой: есть приложение, которое грузит (динамически) библиотеки с некоторым интерфейсом (IInterface).
Все загружаемые библиотеки наследуют некоторое дефолтное поведение от базового класса (Base). Если библиотека не реализует какой-то метод интерфейса, то будет вызван базовый метод. Это чтобы не переписывать в каждой библиотеке одни и те же действия.
Пример загружаемой библиотеки - Derived.
Я привела флаги компиляции и сборки для разных систем (я собираю под линюксом с gcc и icc и под вендой с mingw).
Вроде ничего не забыла, но возможно, что некоторые флаги не нужны для данного примера (я их поместила в квадратные скобки [...]). Просто у меня проект большой и там много чего ещё кроме этого, поэтому там могли оказаться не относящиеся к данной подзадаче параметры. Да, стандартные флаги для библиотек типа -ldl я сюда не выписывала. Выписаны только специфические параметры.
Какие плюсы? Собственно, независимость библиотек от основного кода. Для добавления функционала достаточно перекомпилять загружаемые модули. Базовый функционал класса Base можно менять, не пересобирая библиотеки, которые его используют.

Надеюсь, что в принципе понятно.

Общий файл интерфейса Interface.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef __INTERFACE_H__
#define __INTERFACE_H__
 
// interface
class IInterface
{
public:
    IInterface() {};
    virtual ~IInterface() {};
    virtual void init() = 0;
};
 
// types for class instance creators/destroyers 
typedef IInterface *(*funcInterfaceCreate_type)();
typedef void (*funcInterfaceDelete_type)(IInterface *);
 
#endif // __INTERFACE_H__
Инструкции по сборке базовой библиотеки Base:
gcc,icc:
CXXFLAGS: -fPIC
LDFLAGS: -nodefaultlibs -shared

mingw:
для венды установить дефайн__DLL (для экспорта)
CXXFLAGS:
LDFLAGS: -enable-auto-import [-enable-runtime-pseudo-reloc] -Wl,--kill-at

Заголовок базового класса Base.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#ifndef __BASE_H__
#define __BASE_H__
 
#include "Interface.h"
 
#ifndef __linux__
#ifdef __DLL
#define __BASE_DLL __declspec(dllexport)
#else
#define __BASE_DLL __declspec(dllimport)
#endif
#else
#define __BASE_DLL
#endif
 
class __BASE_DLL Base : public IInterface
{
protected:
    int _param;
public:
    Base();
    virtual ~Base();
    virtual void init();
};
 
#endif
Base.cpp не привожу, он тут не важен. Там можно что-то выполнять, какие-то базовые действия.

Инструкции по сборке библиотеки Derived:
gcc,icc:
CXXFLAGS: -fPIC [-enable-runtime-pseudo-reloc]
LDFLAGS: -nodefaultlibs -shared -lBase

mingw:
для венды установить дефайн __DLL (для экспорта)
CXXFLAGS:
LDFLAGS: -enable-auto-import [-Wl,--allow-multiple-definition]

Заголовок файла основной динамически загружаемой библиотеки Derived.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef __DERIVED_H__
#define __DERIVED_H__
 
#include "Base.h" 
 
#ifndef __linux__
#ifdef __DLL
    #define __DERIVED_DLL __declspec(dllexport)
#else
    #define __DERIVED_DLL __declspec(dllimport)
#endif
#else
#define __DERIVED_DLL
#endif
 
class __DERIVED_DLL Derived : public Base
{
    public:
        Derived();
        virtual ~Derived();
        virtual void init();
};
#endif
Пример реализации основной динамически загружаемой библиотеки Derived.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "Derived.h"
 
Derived::Derived() : Base()
{}
 
Derived::~Derived()
{}
 
void Derived::init()
{
    Base::init();
}
 
#ifdef __cplusplus
extern "C" {
#endif
 
IInterface
#ifndef __linux__
__stdcall __DERIVED_DLL
#endif
*CreateObject()
{
    return (IInterface*)new Derived();
}
 
void
#ifndef __linux__
__stdcall __DERIVED_DLL
#endif
DeleteObject(IInterface *pDerived)
{
    if(pDerived==0) throw;
    delete(pDerived);
}
 
#ifdef __cplusplus
}
#endif
Инструкции по сборке вызывающей программы:
gcc,icc:
CXXFLAGS: -fPIC
LDFLAGS:

mingw:
CXXFLAGS:
LDFLAGS: -enable-auto-import [-enable-runtime-pseudo-reloc] [-Wl,--allow-multiple-definition] -Wl,--kill-at

Пример загрузки/выгрузки библиотеки Derived и использования класса (вызов метода init):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include "IInteface.h"
 
#ifdef __linux__
void *_pDll; // linux handle for dynamic library
#else
HMODULE _hDll; // windows handle for dynamic library
#endif
 
funcInterfaceCreate_type _pFuncCreateObject; //pointer to CreateObject function in dll
funcInterfaceDelete_type _pFuncDeleteObject; //pointer to DeleteObject function in dll
 
IInterface *_pInterface;
 
void load()
{
#ifdef __linux__
    _pDll = dlopen("libDerived.so",RTLD_NOW);
    if(_pDll != 0)
    {
        union
        {
            funcInterfaceCreate_type func;
            void *ptr;
        } uniCreate;
        uniCreate.ptr = dlsym(_pDll,"CreateObject");
        _pFuncCreateObject = uniCreate.func;
        union
        {
            funcInterfaceDelete_type func;
            void *ptr;
        } uniDelete;
        uniDelete.ptr = dlsym(_pDll,"DeleteObject");
        _pFuncDeleteObject = uniDelete.func;
    }
#else
    _hDll = LoadLibrary("Derived.dll");
    if(_hDll != NULL)
    {
        _pFuncCreateObject = (funcInterfaceCreate_type)GetProcAddress(_hDll,"CreateObject");
        _pFuncDeleteObject = (funcInterfaceDelete_type)GetProcAddress(_hDll,"DeleteObject");
    }
#endif
    _pInterface = (*_pFuncCreateObject)();
}
 
void unload()
{
    (*_pFuncDeleteObject)(_pInterface);
 
#ifdef __linux__
    dlclose(_pDll);
#else
    FreeLibrary(_hDll);
#endif
}
 
void use()
{
    _pInterface->init();
}
Примечание: при вызове _pInterface->init() будет вызван метод init класса Derived.


меня давно просили и вот количество просьб превысило порог моей лени и я написала своеобразный "отчёт о проделанной работе". перекопав море документации и наступив на кучу граблей, я всё-таки решила свою задачу. не знаю, подойдёт-не подойдёт, но мне кажется, что эти именно то самое, о чём спрашивал niXman или, во всяком случае, очень близкая к этому задача.

да, кстати: в С++ классы экспортировать можно. только есть некоторые ограничения. но их можно аккуратненько обойти а внутри одного комплятора (это уже совсем шёпотом) можно даже экспортировать классы без фабрики! просто надо маленько ассемблера добавить и знать чуть-чуть реализацию виртуальных таблиц - и дело в кармане. если очень нужно - могу найти статью, как это делается под вендой. но мне это было не нужно, так как у меня задача как раз - наибольшая переносимость по платформам и компиляторам.
1
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
13.03.2011, 02:16  [ТС] 22
Evg, давайте пойдем с другой стороны.
в моей реализации, что конкретно вы считаете неправильным? и почему?

Iron Bug, посмотрел вашу статью. но возник всего один вопрос: что в вашем примере, радикально отличается от моего варианта?! единственное это то, что ваш вариант менее функционален, и сильно хуже спроектирован.
или я что-то пропустил? ... подскажите.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
13.03.2011, 10:24 23
Цитата Сообщение от Iron Bug Посмотреть сообщение
в С++ классы экспортировать можно
Да не экспортируешь их ты. В том понимании, что подразумевается под этим словом в отношении плагинов. Не надо путать понятие экспорта по отношению к библиотеке (когда требуется компиляция программы) и экспорта по отношению к плагину (когда программу перекомпилировать не надо)

Цитата Сообщение от niXman Посмотреть сообщение
Evg, давайте пойдем с другой стороны.
в моей реализации, что конкретно вы считаете неправильным? и почему?
Я уже несколько раз объяснил про одно и то же. По твоей теории я могу написать вот такой "плагин":

C++
1
2
3
4
5
6
7
8
9
10
11
12
struct type_evg: plugin_object {
   type_evg();
   virtual const char* name() const;
   virtual const char* description() const;
   virtual const char* version() const;
   
   virtual void set_evg(int);
   virtual int get_evg() const { return 44; }
   
private:
   int val;
};
Вот теперь скажи мне, как ты заставишь свою программу вызвать метод set_evg?
0
22 / 22 / 2
Регистрация: 06.12.2010
Сообщений: 125
13.03.2011, 11:49 24
Цитата Сообщение от niXman Посмотреть сообщение
Iron Bug, посмотрел вашу статью. но возник всего один вопрос: что в вашем примере, радикально отличается от моего варианта?! единственное это то, что ваш вариант менее функционален, и сильно хуже спроектирован.
или я что-то пропустил? ... подскажите.
это просто кроссплатформенная реализация того, что мне было нужно. с примером, как это собирать. не более. для моей задачи функциональность вполне достаточна и главное: это работает. это не теория, это практика.

Добавлено через 10 минут
Цитата Сообщение от Evg Посмотреть сообщение
Да не экспортируешь их ты. В том понимании, что подразумевается под этим словом в отношении плагинов. Не надо путать понятие экспорта по отношению к библиотеке (когда требуется компиляция программы) и экспорта по отношению к плагину (когда программу перекомпилировать не надо)
вот в моём примере как раз и не надо. просто у меня не плагины, а библиотеки для работы с разными железяками, т.к. я хардварный программист, но не суть. смысл в том, что вызывающей программе не требуется знать ничего, кроме интерфейса. она через него вызывает виртуальные методы и это работает. и дополнительно классы "плагинов" наследуются от базового класса, который сидит в ещё одной библиотеке. таким образом реализовано дефолтное поведение: т.е. если "плагин" не реализовал какой-то метод интерфейса, то будет взят метод из базового класса. базовый класс прицеплен к программе через линковку(но не суть, на самом деле, можно его и через dlopen тащить, просто не требуется), остальное всё грузится динамически через dlopen и оно работает. под разными системами. вызываются перегруженные вирутальные методы интерфейса и т.п. никакой перекомпиляции программы не нужно, ибо она знает только о заголовочнике интрерфейса.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
13.03.2011, 12:02 25
Iron Bug,

1. Твой код - это обычная реализация виртуального наследования, вынесенного в динамическую библиотеку.
2. В твоём коде нет экспорта типов, потому что на Си++ это невозможно. Ты путаешь понятие экспорта типа и экспорта данных или функций. И твой размышления по части манглирования подтверждают это.
3. Твой код работает только под виндами и линуксом, а потому назвать его кроссплатформенным - несколько оптимистично. Тем более, что даже на две платформы с идеологической точки зрения разведено неправильно. Так же мне с ходу непонятно наличие специфических флагов типа -enable-runtime-pseudo-reloc или -Wl,--allow-multiple-definition, но я под виндой практически не работаю

Мне не хотелось бы заниматься подробным обсуждением твоего кода, потому что в данной теме речь идёт совсем о другом. Но твой код, применительно к данной теме - это пример правильной реализации того, как должен выглядеть плагин. Потому что код плагина не выходит за рамки базового интерфейса, предоставленного для работы с плагином. Чего нет в варианте от niXman'а
0
22 / 22 / 2
Регистрация: 06.12.2010
Сообщений: 125
13.03.2011, 12:12 26
P.S. но в моей реализации там есть "фабрики" - функции для создания и уничтожения представителя класса, реализованные внутри библиотеки. это требуется для совместимости библиотек, собранных разными компиляторами. ибо там выделение памяти разное и прочие различия имеются. сами "фабрики" имеют фиксированные имена и также цепляются через dlsym.

Добавлено через 4 минуты
Цитата Сообщение от Evg Посмотреть сообщение
В твоём коде нет экспорта типов, потому что на Си++ это невозможно. Ты путаешь понятие экспорта типа и экспорта данных или функций. И твой размышления по части манглирования подтверждают это.
другой реализации "экспорта класса", кроме экспорта его данных, создать просто нельзя. ибо разные компиляторы создают разные физические реализации объекта. поэтому мой метод - единственно возможный для использования перегруженных методов из динамических библиотек, собственно.
а по части манглирования внутри совместимых на уровне кода (фактически, скомпиленных одним компилятором) библиотек возможна подгрузка куска памяти и инициализация указателей через ассемблер. это и будет чистым "импортом класса". но этот вариант мне не подходит.
что касается кроссплатформенности, то мне нужны только линь и венда. по сути, линь - это моя инициатива. а так, всё написано через буст и исключительно стандартные библиотеки. так что если потребуется реализация для мака или ещё чего-то - это будет требовать минимума изменений в коде. софтина сложная и совсем без ifdef'ов тут не обойтись, увы.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
13.03.2011, 12:21 27
Цитата Сообщение от Iron Bug Посмотреть сообщение
P.S. но в моей реализации там есть "фабрики" - функции для создания и уничтожения представителя класса, реализованные внутри библиотеки. это требуется для совместимости библиотек, собранных разными компиляторами. ибо там выделение памяти разное и прочие различия имеются. сами "фабрики" имеют фиксированные имена и также цепляются через dlsym
Скажем так, чтобы уметь запустить функцию из подгруженной в run-time динамической библиотеки, нужно уметь как-то найти эту функцию. Единственный для этого способ - это по символьному имени функции. Надёжным образом это можно сделать только для тех функций (и переменных), имена которых НЕ подвергаются манглированию со стороны компилятора. Таким свойством обладают только функции (и переменные), реализованные на Си (или на Си++ внутри блока extern "C"). Поэтому такая "фабрика" - это единственный способ вызвать создание объекта извне библиотеки

Цитата Сообщение от Iron Bug Посмотреть сообщение
другой реализации "экспорта класса", кроме экспорта его данных, создать просто нельзя. ибо разные компиляторы создают разные физические реализации объекта
Не только поэтому. В языках Си и Си++ попросту нет возможности работать с динамически созданными типами. Любой тип, с которым идёт работа, должен быть виден в момент компиляции.

Цитата Сообщение от Iron Bug Посмотреть сообщение
поэтому мой метод - единственно возможный для использования перегруженных методов из динамических библиотек, собственно.
Именно так. А способов вызвать "новый" метод (т.е. не описанный в базовом классе), коими являются set и get в варианте niXman'а, попросту нет. В цитате слово "метод" выделил жирным - лучше в таком контексте использовать слово "способ", чтобы не путать с методами языка Си++
0
22 / 22 / 2
Регистрация: 06.12.2010
Сообщений: 125
13.03.2011, 12:37 28
Цитата Сообщение от Evg Посмотреть сообщение
Поэтому такая "фабрика" - это единственный способ вызвать создание объекта извне библиотеки
я уже десятый раз повторяю, что не единственный. я наконец-то нашла линк на ассемблерные приколы с библиотеками:
http://www.codeproject.com/KB/... ingLL.aspx
это реализация для венды, но под линём тоже можно найти аналогичное решение. ведь загрузчик в этой инфе лазит и её инициализирует. значит, и мы можем это сделать. просто это геморно, архитектурно-зависимо и для моей задачи не подходит. но это работает. если очень усираться, то можно написать такие "загрузчики" для всех систем и архитектур. только нафига оно надо...
а про методы именно так и есть. мы должны знать имя. на самом деле, мы можем выкопать его из виртуальной таблицы. но тут включается семантика. ну вот мы выкопали имя, деманглировали (если и это не лень), выковыряли из мангла типы переменных и их количество... а дальше-то что? как это использовать? мы ничего не знаем о семантике метода и его назначении. вот и приплыли.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
13.03.2011, 14:12 29
Цитата Сообщение от Iron Bug Посмотреть сообщение
я уже десятый раз повторяю, что не единственный
Говоря про "способ" я имею в виду человеческие способы. То, что тут написано - это черезж...ное решение для извращенцев, коих я тебе могу выдать миллион.
0
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
13.03.2011, 16:52  [ТС] 30
Цитата Сообщение от Evg Посмотреть сообщение
как ты заставишь свою программу вызвать метод set_evg?
никак.
если программа не знает интерфейса, значит ей вовсе этот плагин не нужен, т.к. невозможно работать с неизвестным типом.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
13.03.2011, 17:08 31
Цитата Сообщение от niXman Посмотреть сообщение
никак.
если программа не знает интерфейса, значит ей вовсе этот плагин не нужен, т.к. невозможно работать с неизвестным типом.
А почему тогда твоя программа знает про класс type1, который как бы является плагином?
0
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
13.03.2011, 17:12  [ТС] 32
Цитата Сообщение от Evg Посмотреть сообщение
почему тогда твоя программа знает про класс type1
эм...
вот ты, для того чтоб выделить память, почему используешь функцию malloc() ?
вот и мне, для того чтоб использовать функционал предоставляемый плагином реализующим type1, нужно знать интерфейс к type1.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
13.03.2011, 17:42 33
Цитата Сообщение от niXman Посмотреть сообщение
вот и мне, для того чтоб использовать функционал предоставляемый плагином реализующим type1, нужно знать интерфейс к type1
Так интерфейсом плагина у тебя является тип i_type. Какого ж фига ты лезешь в type1? И чем использование type1, о котором приложение, вообще говоря, не должно знать, отличается от типа type_evg? Ничем. Я бы сказал это одно и то же

Добавлено через 44 секунды
Цитата Сообщение от niXman Посмотреть сообщение
почему используешь функцию malloc()
Я его использую потому, что он прописан в интерфейсе. А type1 в интерфейсе не прописан
0
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
13.03.2011, 18:03  [ТС] 34
Цитата Сообщение от Evg Посмотреть сообщение
Я его использую потому, что он прописан в интерфейсе. А type1 в интерфейсе не прописан
это называется динамический полиморфизм.
т.е. я работаю на основе информации известной из интерфейса.
а из интерфейса я знаю, что у некоторого типа есть некоторые методы. так же знаю, что поведение методов определено не интерфейсом, а его реализацией в плагине.

Добавлено через 2 минуты
Evg, по моему, мы говорим о разном...
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
13.03.2011, 18:04 35
Цитата Сообщение от niXman Посмотреть сообщение
это называется динамический полиморфизм.
т.е. я работаю на основе информации известной из интерфейса.
а из интерфейса я знаю, что у некоторого типа есть некоторые методы. так же знаю, что поведение методов определено не интерфейсом, а его реализацией в плагине.
В интерфейсе (класс plugin_object) нет методов set и get.

Добавлено через 45 секунд
Цитата Сообщение от niXman Посмотреть сообщение
Evg, по моему, мы говорим о разном...
Я говорю о том, как правильно делать плагины. О чём говоришь ты, я, если честно, не очень понимаю
0
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
13.03.2011, 18:08  [ТС] 36
Цитата Сообщение от Evg Посмотреть сообщение
В интерфейсе (класс plugin_object) нет методов set и get.
потому что он базовый. единственное что реализует plugin_object, так это:
name()
description()
version()

и наследование от этого типа, обязывает реализатора плагина, переопределить эти методы, дабы они возвращали информацию о реализуемом плагине.

Добавлено через 1 минуту
к примеру, я выкину тип plugin_object, и изменю функцию instance() так, чтоб она возвращала указатель на void.
это будет то, о чем говоришь ты?
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
13.03.2011, 18:18 37
Цитата Сообщение от niXman Посмотреть сообщение
потому что он базовый. единственное что реализует plugin_object, так это:
name()
description()
version()

и наследование от этого типа, обязывает реализатора плагина, переопределить эти методы, дабы они возвращали информацию о реализуемом плагине.
Вот всё то, что здесь описано, и является интерфейсом. Типа type1, методов set и get в интерфейсе нет, а следовательно, в основной программе их никак нельзя использовать

Цитата Сообщение от niXman Посмотреть сообщение
к примеру, я выкину тип plugin_object, и изменю функцию instance() так, чтоб она возвращала указатель на void.
это будет то, о чем говоришь ты?
Тогда я не очень понимаю, что в итоге-то останется?

Iron Bug приводила ссылку со своей реализацией. Вот там всё было правильно: из главной программы не было никаких обращений, выходящих за рамки интерфейса.

Вот возьми, к примеру, фотошоп. У него куча всяких фильтров (которые выполняют преобразование изображения). Все они реализованы в виде плагинов и могут добавляться к программе (в том числе и от сторонних разработчиков). Интерфейс плагина, в самом примитивном случае состоит из следующего:
- создать экземпляр класса "плагин". Реально создастся экземпляр пронаследованного класса, но он будет отдан программе в виде указателя на базовый класс
- выполнить преобразование картинки: в некий метод, определённый в базовом классе, отдаётся картинка на вход и принимается картинка на выходе.

Главная программа никоим образом не знает о том, через какой класс всё это реализовано внутри плагина. Знает лишь то, что этот класс является производным классом от базового класса плагина. И главная программа пользуется лишь тем интерфейсом, который описан в базовом классе. Никаких Set и get, который в базовом классе нет
0
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
13.03.2011, 18:36  [ТС] 38
Цитата Сообщение от Evg Посмотреть сообщение
Вот всё то, что здесь описано, и является интерфейсом. Типа type1, методов set и get в интерфейсе нет
так интерфейсы можно наследовать!

Цитата Сообщение от Evg Посмотреть сообщение
Вот возьми, к примеру, фотошоп. У него куча всяких фильтров (которые выполняют преобразование изображения). Все они реализованы в виде плагинов и могут добавляться к программе (в том числе и от сторонних разработчиков). Интерфейс плагина, в самом примитивном случае состоит из следующего:
- создать экземпляр класса "плагин". Реально создастся экземпляр пронаследованного класса, но он будет отдан программе в виде указателя на базовый класс
- выполнить преобразование картинки: в некий метод, определённый в базовом классе, отдаётся картинка на вход и принимается картинка на выходе.
Главная программа никоим образом не знает о том, через какой класс всё это реализовано внутри плагина. Знает лишь то, что этот класс является производным классом от базового класса плагина. И главная программа пользуется лишь тем интерфейсом, который описан в базовом классе. Никаких Set и get, который в базовом классе нет
это все правильно. но я НЕ хочу использовать такой принцип. почему что-то должно меня ограничивать?!
я хочу чтоб плагин type1.so экспортировал функционал согласно интерфейсу type1. поэтому, я получив от плагина инстанс, кастую его к типу type1*, и работаю с указателем на type1.
одновременно, я хочу юзать плагин type2.so. так же, получаю инстанс, и кастую его к типу type2*, и работаю с указателем на type2.
все. невижу противоречий и нелогичности.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
13.03.2011, 18:47 39
Цитата Сообщение от niXman Посмотреть сообщение
но я НЕ хочу использовать такой принцип. почему что-то должно меня ограничивать?!
По определению. Есть функция qsort, одним из параметров которой является указатель на функцию с конкретно заданным прототипом. И ты обязан придерживаться этого интерфейса независимо от желаний "не хочу что-то ограничивать".

Цитата Сообщение от niXman Посмотреть сообщение
все. невижу противоречий и нелогичности
А я вижу. То, что ты хочешь - НЕ является плагином. А является частью программы, оформленной в виде динамической библиотеки. Эту часть ты можешь вообще отдельным классом реализовать без каких-либо наследований от базового класса.

Я могу реализовать динамическую библиотеку, экспортировать в ней функцию trampampam, в которую передаются два int'а, а она будет возвращать их сумму. Далее могу для вычисления суммы двух чисел подключать эту библиотеку через dlopen и работать через ней. Могу назвать эту библиотеку "плагином". И всё будет работать. За исключением того, что это НЕ будет являться плагином
0
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
13.03.2011, 19:00  [ТС] 40
Цитата Сообщение от Evg Посмотреть сообщение
Эту часть ты можешь вообще отдельным классом реализовать без каких-либо наследований от базового класса.
наследование тут нужно чтоб обязать _создателя_плагина_ переопределить методы базового класса.

Цитата Сообщение от Evg Посмотреть сообщение
всё будет работать. За исключением того, что это НЕ будет являться плагином
т.е. все что ты хочешь сказать, так это то, что плагины обязаны соответствовать единому интерфейсу? с этим я не спорю. оно так и есть.
но мне нужна возможность использовать несколько типов интерфейсов обязывая себя знать, какой плагин, какой интерфейс реализует. детали же реализация плагина мне не известны. это мне и требуется.
0
13.03.2011, 19:00
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
13.03.2011, 19:00
Помогаю со студенческими работами здесь

Как видео с камеры отобразить в браузере без использования сторонних плагинов?
Есть простенький веб сервер. на компьютере, на котором развернут сервер, есть встроенная камера....

Реализовать систему плагинов (модулей), каждый из которых должен работать в отдельном потоке
Всем доброго времени суток, не могли бы вы мне помочь реализовать систему плагинов( модулей)....

Взаимодействие плагинов с ядром
Разбираю теорию плагинов. Как выполнить какую либо функцию из .so, это понятно и просто, а вот как...

Установка плагинов cppunit + ecut в Eclipse
Всем доброго времени суток, не могу установить плагины для Eclipse - cppunit + ecut, нужны для юнит...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru