lundi 28 octobre 2019

C/C++ function dynamic loader (helper)

I tried to implement a helper class to easily load .dll or .so files and get function pointer. The following code compile and work well with on ubuntu 16 and VS'2015, but I'm facing issue to have it compiling on Centos 7 (Old GCC 4.8.5)....

It complain about

template< class T> constexpr bool ext_is_function_v = is_function<T>::value;

The error message (see below) doesn't give any clue of why it fails !

error: template declaration of constexpr bool ext_is_function_v = is_function::value;

Is it the constexpr ? or the template alias ? I had a look at the C++11 feature supported by GCC4.8 and everything seems to be ok. But CodeExplorer report issues with using and constexpr

any idea will be welcome

Full code:

#include <type_traits>
namespace std { /* std lib extension with 2 helpers C++14 or C++17*/
    template< bool B, class T = void >
    using ext_enable_if_t = typename enable_if<B, T>::type;
    template< class T> constexpr bool ext_is_function_v = is_function<T>::value;
}
#if defined(_WIN64) || defined(_WIN32)
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#else
#include <dlfcn.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#endif
template<typename F_PTR_T>
class ProcPtr {
public:
    explicit ProcPtr(F_PTR_T ptr) : _ptr(ptr) {}
    template <typename T, typename = std::ext_enable_if_t<std::ext_is_function_v<T>>>
    operator T *() const { return reinterpret_cast<T *>(_ptr); }
private:
    F_PTR_T _ptr;
};
template<typename MODULE_T, typename F_PTR_T>
class DllHelper {
public:
    explicit DllHelper(const char* filename) :
#if defined(_WIN64) || defined(_WIN32)
        _module(LoadLibrary(filename)) 
#else
        _module(dlopen(filename, RTLD_LAZY)) 
#endif
    {
        if(_module == NULL) {
            throw std::runtime_error((boost::format("Error while loading %1%") % filename).str().c_str());
        }
    }

    ~DllHelper() {
#if defined(_WIN64) || defined(_WIN32)
        FreeLibrary(_module);
#else
        dlclose(_module);
#endif
    }

    ProcPtr<F_PTR_T> operator[](const char* proc_name) const {
#if defined(_WIN64) || defined(_WIN32)
        return ProcPtr<F_PTR_T>(GetProcAddress(_module, proc_name));
#else
        return ProcPtr<F_PTR_T>(dlsym(_module, proc_name));
#endif
    }

private:
    MODULE_T _module;
};

Aucun commentaire:

Enregistrer un commentaire