【问题标题】:calling a function via LPVOID with up to 10 arguments of different types通过 LPVOID 调用具有多达 10 个不同类型参数的函数
【发布时间】:2017-11-16 21:29:56
【问题描述】:

我需要调用一个具有 LPVOID 和参数数量的函数。此外,我知道论点的类型和位置。 参数可以是 int、int*、double、double*、string、string* 类型。 由于参数可以按任何顺序排列,因此可能的模板列表会非常大。返回值始终为布尔值。

bool Func1(int);
bool Func1(int*);
bool Func1(double);
(...)
bool Func2(int,int);
bool Func2(int,int*);
(...)

所以这不是一个选项。我尝试使用 std::tuple 但没有成功。 以下示例仅适用于带参数 (int, double) 的函数。

    template <typename R, typename... Args>
    R call(FARPROC fp, Args... args) throw(HRESULT)
    {
        typedef R(__stdcall * function_pointer)(Args...);
        function_pointer P = (function_pointer)fp;
        const auto return_value = (*P)(std::forward<Args>(args)...);
        ().do_cast(fetch_back(args))...);
        return return_value;
     }

(...)
LPVOID function;
int iVal1 = 2;
double dbVal1 = 3.0;
auto t = std::make_tuple(iVal1 , dbVal1);
bool bRes = call<bool>((FARPROC)function, std::get<0>(t), std::get<1>(t));

我正在考虑的是一种基于某些输入(字符串等)创建 std::tuple 的通用方法,例如:auto t = create_tuple("int,int*,int")。

【问题讨论】:

  • 你知道元组也被模板化了,对吧?你可能无法用它规避代码大小的问题。
  • 另外,如果你说输入字符串,你的意思是编译时输入还是运行时输入?
  • 什么是LPVOID,你能解释一下吗?编辑:基本上是void*
  • 无论如何,我认为您的“代码膨胀”问题是没有根据的。您在函数体中的 typedef 和强制转换不会生成任何代码。函数体真正做的就是调用传递的函数指针,这是你无论如何都需要做的工作。在实践中,您可能会看到call 总是被内联(因为特定的模板序列只显示一次)并且只是一些额外的汇编行,无论如何您都需要!

标签: c++ c++11 c++14


【解决方案1】:

我有一个建议,但你必须通过它的地址设置double 变量,就像一个指针一样,因为双变量有 8 个字节,而 void 指针的大小对于 x86 有 4 个字节,对于 x64 有 8 个字节。另外string变量必须设置为指针:

#include "stdafx.h"
#include <string>

using namespace std;

bool Func1(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)
{
    bool result = false;

    int a1 = (int)arg1;
    int a2 = *(int*)arg2;
    double a3 = *(double*)arg3;
    double* a4 = (double*)arg4;
    string a5 = *(string*)arg5;
    string* a6 = (string*)arg6;

    //Do something...

    return result;
}

int main()
{
    bool(*myFun)(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6);
    myFun = &Func1;
    int a1 = 2;
    int a2 = 3;
    double a3 = 4;
    double* a4 = new double(5);
    string a5= "MyData 1";
    string* a6 = new string("MyData 2");

    bool r = (*myFun)((void*)a1, (void*)&a2, (void*)&a3, (void*)a4, (void*)&a5, (void*)a6);
    return 0;
}

希望对你有帮助。

【讨论】:

  • 这看起来不错,但不幸的是我无法更改被调用的函数,因为它们是现有库的一部分。我认为应该可以通过模板来做到这一点,但我尝试了几个想法都没有成功......
【解决方案2】:

我的建议,对于任何对替代品感兴趣的人......

将 LPVOID 函数埋在有意义的 API 下,不再直接使用它。

显然,采用一堆 void *ters 的 LPVOID 函数不是自记录的,所以提供一些自记录的东西。

提供各种构造函数或辅助方法,以接受对 LPVOID 进行特定低级调用所需的值,并提供将值传递给 LPVOID 的转换方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 2017-02-15
    • 2022-11-29
    • 2019-09-23
    • 2020-02-20
    • 1970-01-01
    • 2020-01-23
    相关资源
    最近更新 更多