gpt4 book ai didi

c++ - 包装任何 API 函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:33:08 29 4
gpt4 key购买 nike

我正在包装 Windows API,我希望使错误检查变得易于使用且有用。目前,我有一个全局错误对象,带有一个函数 set 来处理一个新的错误。 set 函数有四个参数:bool Error::set (const int code, const char * file, const char * const function, const int line); 该函数使用文件、函数和行参数以在格式良好的消息中显示它们。

为了简化错误设置,有一个宏 #define setError() error.set (GetLastError(), __FILE__, __FUNCTION__, __LINE__); 这样我就可以使用 setError() 随时响应 API 函数设置的错误,方法是在我调用该 API 函数后添加它。

不幸的是,这导致代码看起来像这样:

SomeAPIFunction();
setError();
AnotherAPIFunction();
setError();

构造函数也有问题:

MyClass:MyClass()
: a (SomeAPIFunction), b (AnotherAPIFunction)
{
setError(); //what if both functions set an error?
}

如您所见,通过使用成员初始值设定项语法,我实际上是在限制自己。

解决这个问题的一种方法是包装每个 API 函数:

int someAPIFunction()
{
int ret = SomeAPIFunction();
setError();
return ret;
}

错误消息的 function 部分会告诉我哪个函数引起了错误。当然,这一定是最糟糕的处理方式。

解决方案似乎是使用可变参数模板。问题是,我不知道我应该做什么才能让他们为此工作。我想最终代码看起来像以下之一:

wrap<int, SomeAPIFunction (5)>();
wrap<int, SomeAPIFunction, 5>();
wrap<int, SomeAPIFunction> (5);

我已经阅读了有关开始可变参数模板的内容,但它们都让我对如何设置这样的东西一无所知。谁能指出我正确的方向?

我在 a similar question 上找到了以下内容:

#include <iostream>

template<void f(void)>
struct Wrap {
void operator()() const {
std::cout << "Pre call hook" << std::endl;
f();
}
};

namespace {
void test_func() {
std::cout << "Real function" << std::endl;
}
}

const Wrap<&test_func> wrapped_test_func = {};

int main() {
wrapped_test_func();
return 0;
}

受访者指出,可变参数模板对于使其足够通用是必要的。这是一个开始,但我很迷茫,很感激在这件事上得到的任何帮助。

最佳答案

我认为您可以使用以下语法使其工作:

wrap(&SomeAPIFunction, arg1, arg2);

关键是让编译器使用类型推导来确定模板类型参数,因为它们很快就会变得非常困惑。

代码应该是这样的:

template<typename TRet, typename... TArgs>
TRet wrap( TRet(WINAPI *api)(TArgs...), TArgs... args )
{
return api(args...);
}

自然地,您会希望使用宏来隐藏函数地址运算符,使用字符串化来存储函数名称,还存储文件名和行号,将所有这些传递给实际的可变参数函数。为此,您需要可变参数宏。事实上,您可以仅使用可变参数宏而不使用模板来完成所有这些操作吗?

关于c++ - 包装任何 API 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9489649/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com