FirebirdSQL logo

Фабрика плагинов

Еще один интерфейс, необходимый для работы плагина —IPluginFactory. Фабрика создаетэкземпляры плагина и возвращает их в диспетчер плагинов. Фабрика обычновыглядит так:

class Factory : public IPluginFactoryImpl<Factory, CheckStatusWrapper>
{
public:
  IPluginBase* createPlugin(CheckStatusWrapper* status,
                            IPluginConfig* factoryParameter)
  {
    MyPlugin* p = new MyPlugin(factoryParameter);
    p->addRef();
    return p;
  }
};

Здесь внимание следует уделить тому факту, что даже в случае, когда кодв функции может генерировать исключения (оператор new может бросать вслучае, когда память исчерпана), то не обязательно всегда вручнуюопределять блок try/catch — реализация интерфейсов Firebird делает этуработу за вас, в реализации IPluginFactory эта обработка происходит вшаблоне IPluginFactoryImpl. Обратите внимание, что обертки статуса поумолчанию выполняют полноценную обработку только для FbException. Ноесли вы работаете над каким-то крупным проектом, то определите своюсобственную оболочку, в этом случае вы можете обрабатывать любой типисключения C++ и передавать полезную информацию об этом из своегоплагина.

Точка инициализации модуля плагина

Когда диспетчер плагинов загружает модуль плагина, он вызывает процедуруинициализации модуля — единственную экспортируемую функцию плагинаFB_PLUGIN_ENTRY_POINT. Для написания кода ей понадобятся две глобальныепеременные — модуль плагина и фабрика плагинов. В нашем случае это:

PluginModule module;

Factory factory;

Если модуль содержит более одного плагина, вам понадобится фабрика длякаждого плагина.

Для FB_PLUGIN_ENTRY_POINT мы не должны забывать, что она должна бытьэкспортирована из модуля плагина, для этого требуется учет некоторыхособенностей ОС. Мы делаем это, используя макрос FB_DLL_EXPORT,определенный в examples/interfaces/ifaceExamples.h. Если вы уверены,что используете плагин только для некоторых конкретных ОС, то вы можетесделать это место немного проще. В минимальном случае функция должнарегистрировать модуль и все фабрики в диспетчере плагинов:

extern "C" void FB_DLL_EXPORT FB_PLUGIN_ENTRY_POINT(IMaster* master)
{
  IPluginManager* pluginManager = master->getPluginManager();
  module.registerMe(pluginManager);
  pluginManager->registerPluginFactory(IPluginManager::TYPE_DB_CRYPT,
                                       "DbCrypt_example",
                                       &factory);
}

Прежде всего, мы вызываем недавно написанную нами функциюPluginModule::registerMe(), которая сохраняет IPluginManager длядальнейшего использования и регистрирует наш модуль плагина. Затемрегистрируем фабрику (или фабрики если в одном модуле будет несколькоплагинов). Мы должны передать правильный тип плагина (допустимые типыперечислены в интерфейсе IPluginManager) и имя, под которым будетзарегистрирован плагин. В простейшем случае он должен совпадать с именемдинамической библиотеки модуля плагина. Это правило поможет вам ненастраивать плагин вручную в plugins.conf.

Обратите внимание — в отличие от приложений плагины не должныиспользовать fb_get_master_interface() для получения IMaster. Вместоэтого следует использовать экземпляр, переданный вFB_PLUGIN_ENTRY_POINT. Если вам нужен мастер-интерфейс в вашем плагине,позаботьтесь об его сохранении в этой функции.