繁体   English   中英

给__stdcall函数指针提供比预期更多的参数

[英]Giving a __stdcall function pointer more arguments than it expects

我正在从供应商提供的dll(全部__stdcall)导入大约1500个函数。 由于繁琐的原因,该dll存在许多版本,其中包含完整功能列表的各个子集(尽管确实存在的所有功能都具有公共接口)。 所有这些函数都返回一个指示错误代码的UINT,但是采用各种类型的各种参数。 当前,如果GetProcAddress失败(因为特定的dll版本中不存在所讨论的函数),则函数指针将保留= nullptr,每次客户端从dll调用函数时都需要检查该指针。 相反,我想将一个指针分配给一个函数,该函数返回适当错误代码的UINT。 提议的解决方案遵循以下原则:

UINT missing_func() {
   return ERR_MISSING_FUNC;
}
.....
typedef UINT(*LibFuncTy)(int a, const char *b, double c);
.....
//GetProcAddress returned nullptr... set generic function
LibFuncTy LibFunc = reinterpret_cast<LibFunctTy>(missing_func);
.....
//programme tries to call library function
errorval = LibFunc(arg1, arg2, arg3);

这种方法可以按书面方式工作(尽管标准没有明确定义),但是一旦调用为__stdcall,它就会失败(大概是因为我们搞砸了堆栈)。 我看过使用(/滥用)绑定,但似乎并不能帮助我尝试做的事情(除非我丢失了某些东西)。 许多库函数调用最终都在一个深层嵌套的循环中结束,因此,在GetProcAddress能够找到该函数的情况下,我不想招致任何(非琐碎的)开销。

是否有实现此行为的“正确”,符合标准的方法,该方法将与__stdcall调用约定一起使用,还是我将不得不生成具有不同参数列表的1500个不同版本的missing_func(),而所有版本都返回相同的值?

每个堆栈帧大小都需要一个伪函数,因为此约定的ret指令会相应地调整堆栈指针。

请注意,有一个标准错误代码表示“未实现”,我认为像E_NOTIMPL类的符号名称。 看看这个。

创建一个在将调用分派到导入函数之前检查nullptr的包装器似乎可行。

template<typename... Args>
struct get_proc_address_wrapper;

template<typename... Args>
struct get_proc_address_wrapper<unsigned(Args...)>
{
    typedef unsigned(__stdcall *func_type)(Args...);
    get_proc_address_wrapper(func_type pf)
        : pf(pf)
    {}

    unsigned operator()(Args... args)
    {
        if (not pf) return static_cast<unsigned>(-1);
        else return (*pf)(args...);
    }

    func_type pf;
};

这是有关如何使用它的演示 如您所见,如果包装器是使用nullptr初始化的,它会优雅地返回错误代码。 我在VS2013上测试了相同的代码,并且返回了相同的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM