[英]Wrapping any API Function
我包裝了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);
我已經閱讀了有關可變參數模板的內容,但是它們都讓我無從得知如何設置類似的東西。 有人能指出我正確的方向嗎?
我在類似的問題上發現了以下內容:
#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...);
}
自然地,您將需要使用宏來隱藏函數地址運算符,使用字符串化存儲函數名稱,並存儲文件名和行號,並將所有這些都傳遞給實際的可變參數函數。 為此,您需要可變參數宏。 實際上,您可以使用可變參數宏而不使用模板來完成所有這些操作嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.