mardi 10 mars 2020

How to check if a dynamic lib correctly implements an interface

I'm trying to load a class from a dynamic librairy. This class need to inherit from an interface named IDisplayModule :

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

I've created a DLLoader class which is used to load a dynamic 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); 
    };     
};

From now, my DLLoader is functional. My problem is if someone :

  • creates an IDisplayModule, but without the getName method
  • creates a dynamic library with a class named WrongClass which inherits from his IDisplayModule

His WrongClass doesn't implement the getName method, and after my DLLoader has loaded his library, my program crashes when I call the getName method.

I understand why it crashes, but I want to avoid it. How can I handle this error ?

Here's my test function :

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;
    }
}

and here's an example of a WrongClass on wrongLib.so :

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

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

Aucun commentaire:

Enregistrer un commentaire