Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Разобраться с плагинами в программе 
:(
    Опции темы
vase
Дата 18.8.2008, 11:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Написал программу, использующу плагины (код класса для загрузки плагина взят с какого-то сайта).
Все работает - проблем нет. Но вызов функции из класса работает только тогда, когда она объявлена была ранее как virtual в файле plugin.h класса PlugIn

Можно ли как-то обойтись без объявления функции или нет? Хочется иметь возможность загрузить из библиотеки любую функцию и получить результат...

Библиотека подгружается след образом:
Код

    DLLFactory<PlugInFactory> so("/home/vase/Projects/panel/src/server/backends/gentoo/services/services.so"); 
    PlugIn *c=so.factory->CreatePlugIn(); 
    c->Show(); 
    c->Test(); 
    delete c; 


Код

class PluginManager {
  public:
    PluginManager(const char *fname);
     virtual ~ PluginManager();


    bool GetFunction(void **, const char *sym_name);

    const char *LastError() {
        return err;
    }
  protected:
    void *h;
    const char *err;
};

class DLLFactoryBase:public PluginManager {
  public:
    DLLFactoryBase(const char *fname, const char *func_name = 0);
    virtual ~ DLLFactoryBase();
    void *(*factory_func) (void);
};

template < class T > class DLLFactory:public DLLFactoryBase {
  public:
  DLLFactory(const char *fname, const char *func_name = 0):DLLFactoryBase(fname, func_name)
    {
        if (factory_func)
            factory = (T *) factory_func();
        else
            factory = 0;
    }
    ~DLLFactory() {
        delete factory;
    }

    T *factory;
};


Код

#include <dlfcn.h> 
#include "modules.h" 

PluginManager::PluginManager( const char *fname ) {
        h=dlopen( fname, RTLD_NOW );
        err=dlerror();
}

PluginManager::~PluginManager() {
        if( h!=0 )
        dlclose(h);
}


bool PluginManager::GetFunction( void **v, const char *sym_name) {
        if( h!=0 ) {
            *v = dlsym( h, sym_name );
            err=dlerror();
            if( err==0 )  return true;
            else return false;
        } else {
            return false;
        }
}

DLLFactoryBase::DLLFactoryBase( const char *fname, const char *factory ) : PluginManager(fname) {
        factory_func=0;
        if( LastError()==0 ) {
            GetFunction( (void **)&factory_func, factory ? factory : "factory0" );
        }

}

DLLFactoryBase::~DLLFactoryBase() {

}


Код

#include <iostream> 
#include "plugin.h" 

PlugIn::PlugIn()
{
        std::cout << "PlugIn Created" << std::endl;
}

PlugIn::~PlugIn()
{
        std::cout << "PlugIn Destroyed" << std::endl;
}



Код

#include "modules.h" 

#ifndef __PLUGIN_H 
#define __PLUGIN_H 


class PlugIn {
  public:
    PlugIn();

    virtual ~ PlugIn();

    virtual void Show() = 0;
};


class PlugInFactory {
  public:
    PlugInFactory() {

    } virtual ~ PlugInFactory() {

    }

    virtual PlugIn *CreatePlugIn() = 0;

};


сам код плагина

Код

#include "services.h" 

Services::Services() {

}


void Services::Show() {
    std::cerr << "I'm service PlugIn!" << std::endl;
}

void Services::Test() {
    std::cerr << "I'm Test from service PlugIn!" << std::endl;
}

Services::~Services() {

}



Код

#include <iostream> 

#include "plugin.h" 


class Services:public PlugIn {

  public:
    Services();
    virtual ~ Services();
    virtual void Show();
    virtual void Test();

};

class PlugInFunFactory:public PlugInFactory {
  public:
    PlugInFunFactory() {

    } ~PlugInFunFactory() {

    }

    virtual PlugIn *CreatePlugIn() {
        return new Services;
    }

};

extern "C" void *factory0(void)
{
    return new PlugInFunFactory;
}



Это сообщение отредактировал(а) vase - 18.8.2008, 11:59
PM MAIL WWW ICQ Jabber   Вверх
bsa
Дата 18.8.2008, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



вообще-то я не очень понимаю, зачем тебе загружать методы класса? Класс как таковой бесполезен без объявления...
Если тебе требуется загружать из плагина объект некоего класса, то этот класс должен быть потомком метакласса, объявление которого известно основной программе, и виртуальные методы переопределены в плагине... Но тут возникает сложность с компиляторами, так как вряд ли будет работать плагин написаный на компиляторе Mingw с программой, созданной в VC...
PM   Вверх
vase
Дата 18.8.2008, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(bsa @ 18.8.2008,  12:30)
вообще-то я не очень понимаю, зачем тебе загружать методы класса? Класс как таковой бесполезен без объявления...
Если тебе требуется загружать из плагина объект некоего класса, то этот класс должен быть потомком метакласса, объявление которого известно основной программе, и виртуальные методы переопределены в плагине... Но тут возникает сложность с компиляторами, так как вряд ли будет работать плагин написаный на компиляторе Mingw с программой, созданной в VC...

То есть в плагин лучше пихать только функции и никаких классов?  Тогда не придется их объявлять ранее ?
PM MAIL WWW ICQ Jabber   Вверх
bsa
Дата 18.8.2008, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(vase @ 18.8.2008,  12:36)
То есть в плагин лучше пихать только функции и никаких классов?  Тогда не придется их объявлять ранее ?

Ну... вообще-то придется, иначе как их ты будешь использовать?
Тут смысл такой, что из плагина ты получаешь несколько заранее известных функции, например: init, process и quit. Первая, допустим, возвращает некий указатель. process - вызывает обработку данные (ему передается указатель), а quit - освобождает память, которая была выделена при инициализации. А вот внутри process, init и quit ты можешь использовать все что угодно. И указатель может указывать на объект класса - из основной программы напрямую обращений к нему нет.
PM   Вверх
vase
Дата 18.8.2008, 13:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(bsa @ 18.8.2008,  12:46)
Цитата(vase @ 18.8.2008,  12:36)
То есть в плагин лучше пихать только функции и никаких классов?  Тогда не придется их объявлять ранее ?

Ну... вообще-то придется, иначе как их ты будешь использовать?
Тут смысл такой, что из плагина ты получаешь несколько заранее известных функции, например: init, process и quit. Первая, допустим, возвращает некий указатель. process - вызывает обработку данные (ему передается указатель), а quit - освобождает память, которая была выделена при инициализации. А вот внутри process, init и quit ты можешь использовать все что угодно. И указатель может указывать на объект класса - из основной программы напрямую обращений к нему нет.

А как тогда делать если надо вызывать разные функции клиентом?
Например, у меня есть приложение которое может создавать и удалять пользователей, а также запускать и останавливать сервисы на сервере. Я клиентом передаю команду, например 
users delete petya
сервер получил команду, загружает библиотеку , которая отвечает за функции с пользователями (например users.so). Далее мне надо вызвать что-то типа process(char *command) , а уже в функции process у меня должен быть switch (command) ..... так ?

Это сообщение отредактировал(а) vase - 18.8.2008, 13:08
PM MAIL WWW ICQ Jabber   Вверх
bsa
Дата 18.8.2008, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



угу
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

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

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

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

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


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

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


 




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


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

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