Динамический загрузчик функций C / C ++ (помощник) - PullRequest
0 голосов
/ 28 октября 2019

Я пытался реализовать вспомогательный класс, чтобы легко загружать файлы .dll или .so и получать указатель на функцию. Следующий код компилируется и хорошо работает с Ubuntu 16 и VS'2015, но я столкнулся с проблемой его компиляции на Centos 7 (Old GCC 4.8.5) ....

Он жалуется на

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

Сообщение об ошибке (см. Ниже) не дает ни малейшего представления о причине сбоя!

ошибка: объявление шаблона constexpr bool ext_is_function_v = is_function :: value;

Это constexpr? или шаблон псевдонима? Я посмотрел на функцию C ++ 11, поддерживаемую GCC4.8, и все вроде бы нормально. Но в отчете CodeExplorer возникают проблемы с с использованием и constexpr

, любая идея приветствуется

Полный код:

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

1 Ответ

0 голосов
/ 29 октября 2019

Наконец, я возвращался к C ++ 11, только не пытаясь расширить пространство имен std.

#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 = typename std::enable_if< std::is_function<T>::value >::type >
    operator T *() const { return reinterpret_cast<T *>(_ptr); }
private:
    F_PTR_T _ptr;
};
...