Приведите значения пакета параметров во время выполнения в зависимости от некоторых метаданных - PullRequest
0 голосов
/ 15 января 2019

Я собрал класс для обработки межплатформенной загрузки общих библиотек (LoadLibrary / GetProcAddress в Windows и dlopen / dlsym в Linux). Функция Call выглядит так -

template <typename ReturnT, typename... Args>
ReturnT Call(const std::string& name, Args... args)
{
        void* functionAddress = GetFunctionAddress(name);

        typedef ReturnT(CALLING_CONVENTION * variadicFunctionPointer)(Args...);

        auto functionPointer = reinterpret_cast<variadicFunctionPointer>(functionAddress);
        const auto returnValue = (*functionPointer)(std::forward<Args>(args)...);

        return returnValue;
}

Использование выглядит следующим образом -

 Library someLib("someLib.dll");

 auto ret = someLib.Call<bool>("SomeCall", "StringParam", 1, true, nullptr, nullptr);   

Это хорошо работает, но когда я застрял, я пытаюсь динамически приводить каждый параметр во время выполнения. Я хочу взять json, загрузить соответствующую библиотеку, привести каждый параметр (мы знаем тип параметра из json), а затем сделать вызов.

 auto result = someLib.Call<bool>(function,
        std::stoi(params.at(0)["value"].get<std::string>()),
        reinterpret_cast<const uint8_t*>(params.at(1)["value"].get<std::string>().c_str()),
        std::stoi(params.at(2)["value"].get<std::string>()),
        digest.data(),
        &bufferSize);

Я пытался использовать функцию преобразования для каждого аргумента пакета параметров, но это не сработает, потому что для этого требуются разные типы возвращаемых данных.

Возможно ли это с помощью C ++ 14?

1 Ответ

0 голосов
/ 15 января 2019

С std::variant (C ++ 17) вы можете сделать что-то вроде:

template <typename Ret>
struct Caller
{
    Caller(const std::string& name) : name(name) {}

    template <typename ... Ts>
    Ret operator ()(Ts... args) const
    {
        void* functionAddress = GetFunctionAddress(name);

        using Func =  Ret(Ts...);

        auto functionPointer = reinterpret_cast<Func*>(functionAddress);
        return (*functionPointer)(std::forward<Ts>(args)...);
    }

    std::string name;
};

А затем:

// Variant constructed from json
std::variant<int, std::string> s{"Hello"};
std::variant<int, std::string> a{40};
std::variant<int, std::string> b{2};

std::visit(Caller<void>("print"), s);
std::cout << std::visit(Caller<int>("add"), a, b) << std::endl;

Демо

...