获取要在C++中动态调用的回调函数的地址
Get the address of a callback function to call dynamically in C++
我正在尝试构建一个可以根据用户输入动态调用任何 Win32 API 函数的应用程序。
我想知道如何在C++中RegisterCallback
函数的行为,因为它似乎非常有用,并且可以获取回调函数的地址。
如何在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");
阅读您的链接,以下是关于回调地址的说法:
如果运行脚本的 exe 是 32 位,则此参数必须介于 0 和 4294967295 之间。如果 exe 为 64 位,则此参数可以是 64 位整数。
因此,您需要将指针地址转换为整数类型。从这个答案中汲取一些灵感,以下代码应该会给你一个提示,说明如何在你的情况下进行转换:
#include <iostream>
#include <cstdint>
bool f() {
return true;
}
int main() {
int iv = *((int*)(&f));
long lv = *((long*)(&f));
long long llv = *((long long*)(&f));
intptr_t ipv = *((intptr_t*)(&f));
std::cout << "int: " << iv << std::endl;
std::cout << "long: " << lv << std::endl;
std::cout << "long long: " << llv << std::endl;
std::cout << "intptr_t: " << ipv << std::endl;
}
对我来说,这打印:
int: -443987883
long: 82192552476362837
long long: 82192552476362837
intptr_t: 82192552476362837
请注意,此处的int
要小以覆盖void*
值。您也应该能够使用LONGLONG
正确转换,否则intptr_t
似乎是正确的数据类型。
- 正在为Xtensa simcall函数编写回调函数
- 如何在C++中使用非静态成员函数作为回调函数
- 从不同的 cpp 调用回调函数会导致bad_function_call
- 如果 C 函数仍然可以间接执行(通过回调函数),那么将它声明为静态函数是否是一种不好的做法?
- C 回调函数在对象 pascal 上崩溃
- 类 Referention 中C++回调函数引用非静态函数
- CURLOPT_INTERLEAVEFUNCTION回调函数始终接收 nullptr 作为用户数据指针
- 动态链接库中C++回调函数
- 我想制作设置鼠标回调函数,以便在仍然按下鼠标左键时连续传递坐标
- 使用回调函数从构造函数调用虚拟/派生方法的替代方法?
- 我可以使用谷歌 v8 在回调函数中获取 JavaScript 函数C++源文本吗?
- 重写另一个方法 [C++] 使用的超类回调函数
- 是否可以影响 C++ 中回调函数的局部变量?
- C++ Qt5 中带有 pigpio 库的回调函数
- 在定时器回调函数中使用 Sleep() 会导致C++出现问题吗?
- C++在赋值或回调函数时重载模板
- 如何用不同的参数类型和数字回调函数
- 如何为Python Swigged C++对象创建和分配回调函数
- 用回调函数替换C++正则表达式
- C++带有回调函数的模板类