Сохранение структуры системы плагинов совместно используемых библиотек при статической компиляции и компоновке

Для библиотеки C ++, которую я сейчас разрабатываю, я увидел преимущества системы плагинов на основе разделяемых библиотек. Функция станет доступной для пользователя библиотеки, только если одна из общих библиотек, находящихся в каталоге, отсканированном во время инициализации, предлагает это.

Используя dlopen, для поиска в общих библиотеках будут использоваться два символа: одна функция, которая возвращает строку с именем реализуемой ими функции, и функция create, которая создает экземпляр класса и возвращает указатель на базовый класс. Что-то вроде этого:

В библиотеке А

#include "Instance.hpp"extern "C" const char* type() {
return "InstanceA";
}
//... class InstanceA definition, inherits from Instance
extern "C" Instance* create() {
return new InstanceA();
}

Библиотека Core будет сканировать каталог плагинов и сохранять карту map-> pointerToCreateFunction для создания новых экземпляров.

Это действительно удобно и довольно стандартно. Если пользовательский код пытается создать экземпляр InstanceX, но никакая разделяемая библиотека не реализует этот тип, будет выдана ошибка, все будет работать отлично.

Но этот каркас будет использоваться также для разработки iOs, и App Store не позволяет загружать сторонние общие объекты. Я хотел бы сохранить эту модульную структуру плагинов даже при загрузке автономной версии библиотеки, которая статически связывает плагины. Обратите внимание, что на уровне управления проектом это будет так же просто, как определить переменную в CMake, которая создает статические версии плагинов и статически связывает их. Это также исключило бы динамическую загрузку части кода.

Чего мне не хватает, так это как инвертировать механизм: хотя для общих объектов базовая библиотека будет использовать файловую систему для изучения возможных типов экземпляров, которые можно использовать, я не знаю, как «зарегистрировать» их без изменения Большая часть кода, и не собирается в фиаско статической инициализации. Похоже, единственный способ добиться этого — заменить код, который сканирует типы, и функцию create, включая все возможные заголовки и имея большой переключатель типа

Instance* theInstance;
if (instanceRequired == "instanceA")
theInstance = new InstanceA();
etc etc...

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

1

Решение

Я делаю такие вещи через те надоедливые статические объекты, которые вызывают, регистрируются в ctor.

Проблема упорядочения решена, если сделать саму карту локальной статической, чтобы она создавалась при первом вызове клиента, откуда бы он ни исходил. (Потоки и подобные проблемы уклоняются, ограничивая запуск потоков до основного времени, и к этому времени все важные вещи становятся обязательными.)


class RegMap;  // the registry
RegMap& GetRegistry(); // the singleton access function; you can make a separate const/nonconst version or provide another wrapper for registering

//    implementation in core.cpp:
RegMap& GetRegistry()
{
static RegMap m;
return m;
}

//in client ctor:
GetRegistry().Register( key, func);
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]