C# 回调函数在构建和动态链接库时的作用
回调函数等同于C#(.NET)中的事件 我对回调函数的理解是,它是一个通过引用该函数来调用的函数 示例代码为:C# 回调函数在构建和动态链接库时的作用,c#,c++,windows,visual-c++,function-pointers,C#,C++,Windows,Visual C++,Function Pointers,回调函数等同于C#(.NET)中的事件 我对回调函数的理解是,它是一个通过引用该函数来调用的函数 示例代码为: void cbfunc() { printf("called"); } int main () { void (*callback)(void); callback=(void *)cbfunc; callback(); return 0; } 现在我不明白的是,在从DLL向客户机发送通知方面,这是如何充分使用的 假设我想在
void cbfunc()
{
printf("called");
}
int main ()
{
void (*callback)(void);
callback=(void *)cbfunc;
callback();
return 0;
}
现在我不明白的是,在从DLL向客户机发送通知方面,这是如何充分使用的
假设我想在接收DLL method2()上的数据时执行一些method1()
与.NET中的事件进行任何比较都非常有帮助。您将指针传递给第三方例程(不必是DLL),当需要通知时,克隆指针会“回调” 它与.net事件类似,后者也是一种回调类型
// Begin library/dll Public Interface used by an executable
class mydll_interface {
public:
typedef void (*callback_func_t)();
public:
virtual void do_something() = 0;
virtual void registerFunction( callback_func_t ) = 0;
};
static mydll_interface* getMyDllInterface();
// End library/dll Public Interface used by an executable
// Begin library/dll Private implementation
class mydll_implementation : public mydll_interface {
public:
void do_something() {
printf("Hello World\n");
_callback_func();
}
void registerFunction( callback_func_t c) {
_callback_func = c;
}
private:
callback_func_t _callback_func;
};
static mydll_interface* getMyDllInterface() {
return new mydll_implementation();
};
// End library/dll Private implementation
// Begin main executable code
void myMainAppFunc() {
printf("hello World Again\n");
}
int main() {
mydll_interface* iface = getMyDllInterface();
iface->registerFunction(&myMainAppFunc);
iface->do_something();
};
// End main executable code
// Begin library/dll Public Interface used by an executable
class mydll_interface {
public:
typedef void (*callback_func_t)();
public:
virtual void do_something() = 0;
virtual void registerFunction( callback_func_t ) = 0;
};
static mydll_interface* getMyDllInterface();
// End library/dll Public Interface used by an executable
// Begin library/dll Private implementation
class mydll_implementation : public mydll_interface {
public:
void do_something() {
printf("Hello World\n");
_callback_func();
}
void registerFunction( callback_func_t c) {
_callback_func = c;
}
private:
callback_func_t _callback_func;
};
static mydll_interface* getMyDllInterface() {
return new mydll_implementation();
};
// End library/dll Private implementation
// Begin main executable code
void myMainAppFunc() {
printf("hello World Again\n");
}
int main() {
mydll_interface* iface = getMyDllInterface();
iface->registerFunction(&myMainAppFunc);
iface->do_something();
};
// End main executable code
void
CALLBACK
MyTimerCallback(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
// do something
}
...
TIMERPROC fn = &MyTimerCallback;
int delay = 500;
SetTimer(NULL,0,delay,fn);
调用SetTimer并传入回调函数,允许操作系统在每次计时器计时时回调函数。当然,这里没有多播功能,特别是在SetTimer的情况下,回调函数必须是C函数或静态类方法。没有与函数关联的类或对象实例
类似的模式也可以在.NET中实现——我确信.NET有自己的计时器范例,但我们可以暂时假设它实现了一个使用TimerDelegate的SetTimer函数
在用户代码中,在对象中,您将MyTimerProc定义为一个具有与委托匹配的签名的函数。然后像这样调用它
TimerDelegate d = new TimerDelegate(myObject.MyTimerProc);
SetTimer(0,0,delay,d);
或者,如果“timers”是一个与TimerDelegate匹配的事件,那么等效的C#代码如下所示:
timers += new TimerDelegate(myObject.MyTimerProc);
注意:我的C#非常生疏,所以不要将这些代码示例作为最佳实践,甚至工作代码的示例:p
当定义自己的回调函数时,总是定义回调函数以获取空缺*“上下文”参数是一个很好的做法,因为这允许C++程序员存储他们的“这个”指针并检索它。
// the first parameter to the callback fn is a void* user supplied context parameter
typedef void (CALLBACK* MyCallbackFn)(void* context, int etc);
// and, the dll export function always takes a function pointer, context parameter pair.
DLL_EXPORT void SomeExportedFn(MyCallbackFn, void* context);
回调函数的作用与C#中的委托类似 例如,Win32 API提供了一个计时服务,可以通过调用SetTimer来访问该服务。SetTimer由系统DLL导出,但其机制与在用户DLL中使用的机制完全相同。在代码中,您可以通过执行以下操作来访问计时器:
void
CALLBACK
MyTimerCallback(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
// do something
}
...
TIMERPROC fn = &MyTimerCallback;
int delay = 500;
SetTimer(NULL,0,delay,fn);
调用SetTimer并传入回调函数,允许操作系统在每次计时器计时时回调函数。当然,这里没有多播功能,特别是在SetTimer的情况下,回调函数必须是C函数或静态类方法。没有与函数关联的类或对象实例
类似的模式也可以在.NET中实现——我确信.NET有自己的计时器范例,但我们可以暂时假设它实现了一个使用TimerDelegate的SetTimer函数
在用户代码中,在对象中,您将MyTimerProc定义为一个具有与委托匹配的签名的函数。然后像这样调用它
TimerDelegate d = new TimerDelegate(myObject.MyTimerProc);
SetTimer(0,0,delay,d);
或者,如果“timers”是一个与TimerDelegate匹配的事件,那么等效的C#代码如下所示:
timers += new TimerDelegate(myObject.MyTimerProc);
注意:我的C#非常生疏,所以不要将这些代码示例作为最佳实践,甚至工作代码的示例:p
当定义自己的回调函数时,总是定义回调函数以获取空缺*“上下文”参数是一个很好的做法,因为这允许C++程序员存储他们的“这个”指针并检索它。
// the first parameter to the callback fn is a void* user supplied context parameter
typedef void (CALLBACK* MyCallbackFn)(void* context, int etc);
// and, the dll export function always takes a function pointer, context parameter pair.
DLL_EXPORT void SomeExportedFn(MyCallbackFn, void* context);
回调和接口类是管理代码边界的好方法。它们有助于在代码中创建正式的边界和/或层,而不是将所有内容集中在一起。在处理大型软件解决方案时,这是必要的 下面是一个如何使用回调和接口类的示例。在library/dll代码中,唯一应该向主可执行文件公开的是myddl_接口类和函数getMyDllInterface()。使用这样的接口类完全隐藏了主可执行文件的实现细节。接口类还允许主可执行文件向其注册稍后将执行的函数(即回调)
回调和接口类是管理代码边界的好方法。它们有助于在代码中创建正式的边界和/或层,而不是将所有内容集中在一起。在处理大型软件解决方案时,这是必要的 下面是一个如何使用回调和接口类的示例。在库/dll代码中,唯一应该向