簡體   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