Форум программистов, компьютерный форум, киберфорум
Наши страницы

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

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ XML ошибка формата http://www.cyberforum.ru/cpp/thread123873.html
не знаю куда еще написать, браузер при открытии xml пишет XML Parsing Error: not well-formed Location:...
C++ Правильное чтение из файла! Помогите пожалуйста, уже опробовал все((( Суть задачи такая, есть файл data.txt в нем есть числа выглядит он так: 200,100,100, 100, 300 Ниже представлен код программы, которая просит ввести... http://www.cyberforum.ru/cpp/thread123639.html
C++ Функции!
Приношу свои извинения за этот глупый вопрос, я начинающий программист и сейчас прохожу урок Функции, но не могу понять, очень не понятно описывается, подскажите что такое функции и для чего они...
C++ Любопытственная ошибка
В программе глобально объявлен буфер для передачи сообщений по каналу: char MsgBuf; Далее при формировани сообщения: MsgBuf="go"; Следующая ошибка: error C2440: '=' : cannot convert from...
C++ Перевод из Паскаля в СИ. http://www.cyberforum.ru/cpp/thread123250.html
Доброго времени суток. Помогите перевести программу из паскаля в СИ. 1 программа: Program oblast; uses crt; var a,b,z:real; c:boolean; begin clrscr; write('Введите a='); readln(a);
C++ Динамические потоки c обрабатываемой памятью Нужна ваша помощь. #include "WinThread.h" LPVOID hf1,hf2,hf3; iXml* Tr; AnsiString str; std::vector<GraphObj *> *GNO; typedef struct Params подробнее

Показать сообщение отдельно
Iron Bug
22 / 22 / 0
Регистрация: 06.12.2010
Сообщений: 125
12.03.2011, 19:48
эхх... чем пояснять и доказывать, вот вам пример:
Я тут обнаружила потребность народа в некотором примере насчёт использования динамических библиотек.
Вот, вытащила из своего проекта куски, относящиеся к загрузке и вызовам.
Смысл примера такой: есть приложение, которое грузит (динамически) библиотеки с некоторым интерфейсом (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
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.