簡體   English   中英

包裝任何API函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM