Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
Другие темы раздела
C++ ./massdown: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.11' not found (required by ./massdown) http://www.cyberforum.ru/cpp/thread98890.html
всем хай! собираю свою программу на новом железе х86_64 долго не получалось скомпилить. при линковке получал вот такое сообщение: relocation R_X86_64_32 against `a local symbol' я так понял, это из-за того что часть библиотек от которых зависит цель, были собраны как 32-ух битные. но с этим вроде все нормально, пересобрал все либы - скомпилировалось. теперь при запуске получаю такое...
C++ Как понять этот константный указатель? В общем, имеется класс Cat. Объект класса - SimpleCat. И имеется функция с константым указателем: const SimpleCat* const FunctionTwo(const SimpleCat* const theCat) Что обозначают все эти const? Насколько я понимаю: 1. Константный указатель. 2. Может ссылаться только на FunctionTwo 3. Ничего не изменяет в объекте. 4. Ничего не делает с объектом theCat. http://www.cyberforum.ru/cpp/thread82125.html
C++ Перехват и подмена вызываемых функций
Здравствуйте. Нужно подменить вызов таких функций как open(), lstat(), stat(), read(), write(), mkdir(), chdir(), getcwd() для определенного процесса. Интересует мнение других. Как бы вы реализовали эту задачу. Спасибо!
 

Показать сообщение отдельно
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 или, во всяком случае, очень близкая к этому задача.

да, кстати: в С++ классы экспортировать можно. только есть некоторые ограничения. но их можно аккуратненько обойти а внутри одного комплятора (это уже совсем шёпотом) можно даже экспортировать классы без фабрики! просто надо маленько ассемблера добавить и знать чуть-чуть реализацию виртуальных таблиц - и дело в кармане. если очень нужно - могу найти статью, как это делается под вендой. но мне это было не нужно, так как у меня задача как раз - наибольшая переносимость по платформам и компиляторам.
 
Текущее время: 01:25. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru