Определение интерфейса абстрактного класса в разделяемой библиотеке

Скажем, у меня есть абстрактный базовый класс, определенный так:

interface.hpp

#ifndef INTERFACE_HPP
#define INTERFACE_HPP 1

class interface{
public:
virtual void func() = 0;
};

#endif // INTERFACE_HPP

Затем я собираю модуль перевода test.cpp в общий объект test.so:

test.cpp

#include "interface.hpp"#include <iostream>

class test_interface: public interface{
public:
void func(){std::cout << "test_interface::func() called\n";}
};

extern "C"interface &get_interface(){
static test_interface test;
return test;
}

Если я открою этот общий объект в исполняемом файле и попытаюсь вызвать get_interface как это:

#include <dlfcn.h>
#include "interface.hpp"
int main(){
void *handle = dlopen("test.so", RTLD_LAZY);
void *func = dlsym(handle, "get_interface");

interface &i = reinterpret_cast<interface &(*)()>(func)();
i.func(); // print "test_interface::func() called"
dlclose(handle);
}

(просто сделайте вид, что я сделал проверку ошибок)

Правильно ли определено поведение? Или я наступаю на собственные пальцы, полагая, что это всегда будет работать?

Имейте в виду, что я буду использовать только clang и gcc

1

Решение

Одна ошибка в том, что вы хотите protected: ~interface() отговорить клиентов от удаления interface,

Второй практический вопрос заключается в том, что если вы измените interfaceне забудьте добавить методы на конец только класса, и не добавляйте новые виртуальные переопределения (функции с тем же именем). (На практике я видел кластеризацию переопределений, даже если они не кластеризованы в заголовочном файле).

Если вы хотите больше, чем просто один интерфейс (скажем, ваш интерфейс наследуется от 2 других интерфейсов), используйте virtual наследование. Добавление нового virtual Родители после того, как факт, по моему опыту оказался проблематичным, а также.

Ничто из этого не определяется стандартом C ++, который не зависит от темы бинарных интерфейсов и загрузки кода во время выполнения. Тем не менее, вышеизложенное является моим опытом использования подобной техники (по общему признанию, с указателями вместо ссылок и использованием MSVC вместо gcc / clang).

Вы должны отслеживать, что такое ABI на используемых вами компиляторах. Если вы пройдете std структуры над таким интерфейсом, помните, что они иногда меняют расположение (std::string в gcc переходя от ссылки, подсчитанной к нет, например, или std::list получение O (1) size), и они не так уж и вероятны для совместимости компоновки между компиляторами (ну, стандартные библиотеки, которые разные компиляторы по умолчанию используют по-разному).

0

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


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector