Как проверить, правильно ли в Dynami c lib реализован интерфейс - PullRequest
0 голосов
/ 10 марта 2020

Я пытаюсь загрузить класс из динамического c библиотеки. Этот класс должен наследоваться от интерфейса с именем IDisplayModule:

class IDisplayModule {
public:
    virtual ~IDisplayModule() = default;
    virtual const std::string &getName() const = 0;
};

Я создал класс DLLoader, который используется для загрузки динамического c lib:

template <typename T>
class DLLoader {
private:
    std::string _libraryPath;
    void *_handle;

public:
    DLLoader<T>(const std::string &libraryPath) try : _libraryPath(libraryPath), _handle(NULL) {
        _handle = dlopen(_libraryPath.c_str(), RTLD_GLOBAL | RTLD_NOW);
        if (!_handle)
            throw DLLoaderException("On dlopen of " + _libraryPath, "DLLoader");
    } catch (DLLoaderException &e) {
        throw e;
    }; 

    T *getInstance(const std::string &entryPoint) const {
        T *(*fptr)(void);
        T *obj = NULL;

        void *ret = dlsym(_handle, entryPoint.c_str());
        if (!ret)
            throw DLLoaderException("On dlsym of " + _libraryPath + dlerror() + "DLLoader");
        fptr = reinterpret_cast<T *(*)(void)>(ret);
        obj = dynamic_cast<T *>(fptr());
        if (!obj)
            throw DLLoaderException("On cast of " + _libraryPath + dlerror() + "DLLoader");
        return (obj);
    };

    ~DLLoader<T>() { 
        dlclose(_handle); 
    };     
};

С этого момента мой DLLoader работает. Моя проблема, если кто-то:

  • создает IDisplayModule, но без getName метода
  • создает динамическую c библиотеку с классом с именем WrongClass, который наследует из его IDisplayModule

Его WrongClass не реализует метод getName, и после того, как мой DLLoader загрузил его библиотеку, моя программа падает, когда я вызовите метод getName.

Я понимаю, почему он падает , но я хочу избежать этого. Как я могу обработать эту ошибку?

Вот моя тестовая функция:

int main(void)
{
    try {
        DLLoader<IDisplayModule> lib = DLLoader<IDisplayModule>("./wrongLib.so");
        IDisplayModule *libInstance = lib.getInstance("entryPoint");
        std::cout << libInstance->getName() << std::endl;
    } catch (DLLoaderException &e) {
        std::cerr << e.what() << std::endl;
    }
}

и вот пример WrongClass на wrongLib.so:

class WrongClass : public IDisplayModule {
private:
    std::string _name;
public:
    lib1();
   ~lib1();
};

extern "C" {
    IDisplayModule *entryPoint()
        return (new WrongClass());
}
...