c++ - 获取回调函数的地址以在C++中动态调用

标签 c++ dynamic callback

我正在尝试构建一个可以根据用户输入动态调用任何 Win32 API 函数的应用程序。

我想知道如何才能拥有函数 RegisterCallback 的行为在C++中,因为它看起来非常有用,它可以获取回调函数的地址。

如何使用 C++ 中类似的函数实现相同的行为?

我已经成功实现了一个可以调用任何动态库的函数,但陷入了这样的动态回调。

例如,我可以使用我的函数调用 EnumWindows API,如下所示:

CallLibFunction(GetProcAddress(LoadLibrary(L"User32.dll"), "EnumWindows"), ParamArray, 2, ExepInfo);

提前致谢。

编辑:我会解释更多。

假设我有以下代码:

回调函数:

BOOL CALLBACK EnumWindowsProc(__in HWND hWnd, __in LPARAM lParam)
{
    return TRUE;
}

主要功能:

EnumWindows(EnumWindowsProc, NULL);

以上是任何人都可以使用 API 函数的常用方式。我希望它被这样称呼:

LONGLONG CallbackAddress = <Some Function to get address>&EnumWindowsProc

ParamArray[1].type = VT_I8;
ParamArray[1].llval = CallbackAddress; // Address of `EnumWindowsProc`.

最后动态调用它,如下所示:

CallLibFunction(GetProcAddress(LoadLibrary(L"User32.dll"), "EnumWindows"), ParamArray, 2, ExepInfo);

最佳答案

首先,您需要声明一个指针类型来保存回调的地址。在 C++ 中,函数的基本定义有点奇怪。更复杂的是,在 C++ 中,我们有函数、函数对象和模板类型。

标准提供了一个基本的函数模板类型:std::function。这个类型 保存的不是函数指针,而是可调用对象。

#include <functional>

要声明特定的函数类型,请将其签名作为模板参数传递给 std::function。

typedef std::function<int(const char*)> StdFreeFunc;

// you can also define types for member functions, and define 
// member function pointers this way
struct A{};
typedef std::function<int A::*(const char*)> StdMemberFunc;

// member callable objects are called with this syntax:
// (obj.*callable)(args); or (obj->*callable)(args); 
// the parenthesis are often required to keep the compiler happy

// A callable object:
struct CallMe
{
    int xy;
    int operator()(const char*) { /*...*/ return xy; } 
};

std::function 与函数对象、lambda 和常规函数指针兼容(见下文)。最适合仅使用 C++ 的东西。

struct AStruct
{
   StdFreeFunc callback_;   // we hold a value, not a pointer

   void setCallback(StdFreeFunc&& cb)  // pass by value, reference, const ref, 
   {                                   // move... like any object type 
       callback_ = cb; 
   };

   int callCallback(const char* str) 
   { 
       if (callback_) // callable object has a bool() operator to check if valid !!
           return (callback_)(str); 

       // the parenthesis and is optional, so this is the same:
       if (callback_)
           return callback_(str):
   }
};

// example with callable object:
AStruct as, ar;
as.setCallback(CallMe{42});   // we can pass an object with data
ar.setCallback(CallMe{84});   // to obtain different effects

as.callCallback("prints fourty two");
ar.callCallback("prints eighty four");

C 风格函数指针

在 C++ 之前,有 C。这就是 C 的实现方式,而且它确实可以编译。 C 风格函数指针的缺点是它们与函数对象不兼容。另一方面,它们与 C 以及许多其他语言(例如 PASCAL、VB 等)兼容。

例如,以 const char* 作为参数并返回 int 的函数类型写为:

typedef int (CallBack)(const char*);

最常见的形式是声明一个指针,因为这就是存储的内容。如:

typedef int (*CallBack)(const char*);

// you can specify extra call specifications

typedef int (__stdcall * CallBack)(const char*);  // uses PASCAL calling


// exmample:

struct YourStruct
{ 
   //...
   Callback callback_{nullptr};  // this is a pointer initialize to nullptr
   //...
   void setCallback(Callback cb)
   { 
       // call as ys.setCallback(AFunction)
       // or      ys.setCallback(&AFunction)
       callback_ = cb; 
   };

   int callCallback(const char* str) 
   { 
       if (callback_)   // always check if valid !!
           return (*callback_)(str); 

       // the parenthesis and the * are optional, so this is the same:
       if (callback_)
           return callback_(str):
   }
};

int UserFunction(const char*) { /*...*/ return 0; }

YourStruct ys;
ys.setCallback(&UserFunction);
ys.callCallback("hello");

关于c++ - 获取回调函数的地址以在C++中动态调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45752078/

相关文章:

c++ - 解析位图文件时,如何替换WORD和DWORD数据类型?

java - 如何在flex中创建动态数据网格

php - SEO 和 ajax 加载的内容链接

javascript 回调 - 如何使用回调

C++类成员变量知道自己的偏移量

c++ - Ncurses:创建下一个窗口后无法在上一个窗口中写入

c++ - 函数/仿函数作为模板参数。它们可以储存吗?

c++ - 为什么 (*callback)() 有效,而 *callback() 或 *callback 在 C++ 中不起作用

c++ - 我是否需要处理下面代码中的任何错误情况?

c - 在某些测试用例之后,堆被损坏