我正在尝试构建一个可以根据用户输入动态调用任何 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/