LINUX.ORG.RU

C++, классы в подружаемых .so


0

0

Есть некоторый класс, объявленный и реализованный в .cc файле.
В этом же файле есть глобальные функции createClass, deleteClass.
Этот .cc файл компилируется в .so модуль и затем подгружается в
основную программу. Вопрос такой: как можно определить реализует ли
этот класс, в загруженном .so, определенный интерфейс.

class ModuleManager {
    public:
        template <class T_Interface>
        T_Interface* findModuleForInterface() const
        {
            // for each of loaded modules {
            //   if loaded module implements T_Interface {  // <- ??
            //     if module instance is 0 {
            //       create module instance
            //     }
            //     return module instance
            //   }
            // }
            // return 0
        }
};

Если добавить в .cc файл модуля еще одну функцию:
bool probeClass(const std::type_info& pInfo)
{
  return strcmp(typeid(SupportedIfaceA).name(), pInfo.name()) == 0 ||
         strcmp(typeid(SupportedIfaceB).name(), pInfo.name()) == 0;
}
Все вроде бы получается. Но только на std::type_info::name()
рассчитывать нельзя.

Как вообще правильно реализуется такое на C++ (приложение работает
с абстрактными интерфейсами; реализации интерфейсов загружаются из
.so файлов; поиск реализации для заданного интерфейса)?

Ответ на: комментарий от Begemoth

Похоже нет. Либо я ужо совсем ничего не понимаю X-/ Как тут можно использовать dynamic_cast?

Сравнивать объекты std::type_info не получается, там в модуле свое std::type_info ...

Эх, видимо придеться полагаться на std::type_info::name() ...
Много ли таких реализаций, в которых type_info::name() вернет пустую строку? Надеюсь нет ...

binnehex
() автор топика

Гадость тут в том, что .so и хост содержат свои копии typeinfo каждого класса. Поэтому средства C++ в этом случае отпадают. Придется делать ручками в явном виде: завести enum кодов интерфейсов, сгородить метод запроса интерфейса по коду.

Что-то типа:

struct IUnknown
{
virtual void* getAs( long _code ) = 0;
virtual void const* getAs( long _code ) const = 0;
};

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от binnehex

class A : public I1, public I2, public Object
{
    public:
        virtual ~A(){}
};

void foo( Object &o )
{
    try
    {
        I1 &ref = dynamic_cast<I1 &>( o );
    }
    catch( std::bad_cast & )
    {
        std::cerr << "shit!" << std::endl;
    }
}

yz
()
Ответ на: комментарий от binnehex

Ну из so-шки получаем значение типа Object*:

Object* o = dlsym(so_handle, symbol_name);
if (Iface* i = dynamic_cast<Iface*>(o)) {
 ....
}

Я года 3 назад писал что-то подобное, но исходник канул с Лету... 
Сейчас под рукой компилятора С++ нет...

ЗЫ: может просто я тебя неправильно понял...

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

dynamic_cast использует то самое type_info. А таких type_info два - один в основном модуле, другой в .so. Хоть они и type_info того же класса, но расположены по разным адресам и сравнение в

bool type_info::operator==(const type_info& other)
{
return this == &other;
}

не работает. Поправьте если не прав.

ЗЫ: пока ковырялся, нашел интересную и новую для себя штуку - cplus_demangle из libiberty. То есть
cplus_demangle(typeid(MyType).name(), DMGL_GNU_V3)
вернет читабельное имя типа. Здорово ...

binnehex
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.