В настоящее время я работаю над игровым движком, который реализует архитектуру на основе фреймворков.
Эти платформы динамически загружаются в движок с помощью библиотек .so.
Чтобы проиллюстрировать использование фреймворков, вот небольшая картинка:
Взаимодействие с движком
(обратите внимание, что движок также знает о типах FrameworkTpl и SpecificFrameworkTpl)
Как мы видим, specificFrameworkImplementation класс компилируется как разделяемая библиотека (.so) и наследуется от specificFrameworkTpl которые сами по себе наследуют FrameworkTpl.
После компиляции библиотека загружается в движок во время выполнения, и экземпляр платформы извлекается как FrameworkTpl.
В это время, если я позвоню FrameworkTpl метод, он будет работать как шарм (что довольно очевидно, да …).
Тем не менее, если я попытаюсь бросить этот экземпляр на specificFrameworkTpl с помощью dynamic_cast
, он вернет nullptr
,
Благодаря моему исследованию (которое длилось около недели при чтении man-страниц и ответов StackOverflow), я видел людей, говорящих о флагах, которые нужно передать dlopen
функция, такая как RTLD_NOW или удалить как RTLD_LOCAL в пользу RTLD_GLOBAL, но ни один из них не работал для меня, то же самое для флагов g ++ (-rdynamic
).
Код:
Вот пример с GuiFrameworkTpl
как specificFrameworkTpl
а также FrameworkUI
за specificFrameworkImplementation
,
FrameworkTpl
class FrameworkTpl
{
protected:
std::string _name;
public:
FrameworkTpl(const std::string &name):
_name(name)
{
}
virtual ~FrameworkTpl(void)
{
}
public:
virtual std::string getName(void) const
{
return (this->_name);
}
};
GuiFrameworkTpl
class GuiFrameworkTpl : public FrameworkTpl
{
public:
GuiFrameworkTpl(const std::string & name) :
FrameworkTpl(name)
{
}
virtual ~GuiFrameworkTpl(void)
{
}
virtual void displaySquare(int x, int y, int size) = 0;
};
FrameworkUI
class FrameworkUI : public GuiFrameworkTpl
{
public:
FrameworkUI();
~FrameworkUI();
public:
void displaySquare(int x, int y, int size);
};
extern "C"{
FrameworkUI* CObject()
{
return (new FrameworkUI);
}
void DObject(FrameworkUI* obj)
{
delete obj;
}
}
Приложение, которое использует библиотеку и приводит из нее материал:
(Здесь Xxx из предыдущих классов используется как «Gui»)
GuiFrameworkTpl* GUISystem::cast_f(const std::shared_ptr<FrameworkTpl>& src)
{
auto ptr = src.get();
Log::print(ptr);
if (!ptr) return nullptr;
Log::inform(ptr->getName());
auto dst = dynamic_cast<GuiFrameworkTpl*>(ptr);
Log::print(dst);
return dst;
}
Что я должен иметь:
Когда я загружаю свою библиотеку и звоню CObject()
это должно создать экземпляр FrameworkUI который я получаю в FrameworkTpl, тогда я просто должен был бы выполнить dynamic_cast как GuiFrameworkTpl для того, чтобы получить доступ к определенному методу.
Что у меня действительно есть:
Когда я загружаю свою библиотеку и звоню CObject()
это создает экземпляр FrameworkUI который я храню в FrameworkTpl (кстати, я могу позвонить getName()
метод успешно, поэтому экземпляр действителен). Но когда я пытаюсь GuiFrameworkTpl, это дает мне nullptr
,
Последняя функция напечатать это:
0xc0c200
[INFO]: FrameworkUI
0
Если кто-нибудь знает, как решить эту проблему, я был бы очень признателен,
заранее спасибо
Задача ещё не решена.
Других решений пока нет …