进程间可否使用c 回调函数的使用

2012年11月 挨踢职涯大版内专家分月排行榜第二2011年9月 Linux/Unix社区大版内专家分月排行榜第二
2012年1月 Linux/Unix社区大版内专家分月排行榜第三2011年8月 C/C++大版内专家分月排行榜第三2011年8月 Linux/Unix社区大版内专家分月排行榜第三2010年4月 C/C++大版内专家分月排行榜第三
2012年11月 挨踢职涯大版内专家分月排行榜第二2011年9月 Linux/Unix社区大版内专家分月排行榜第二
2012年1月 Linux/Unix社区大版内专家分月排行榜第三2011年8月 C/C++大版内专家分月排行榜第三2011年8月 Linux/Unix社区大版内专家分月排行榜第三2010年4月 C/C++大版内专家分月排行榜第三
2012年8月 C/C++大版内专家分月排行榜第三2012年7月 C/C++大版内专家分月排行榜第三
2013年12月 C/C++大版内专家分月排行榜第二2013年12月 Linux/Unix社区大版内专家分月排行榜第二2013年11月 C/C++大版内专家分月排行榜第二2013年10月 C/C++大版内专家分月排行榜第二
本帖子已过去太久远了,不再提供回复功能。(此方案完全可行,只是我忘掉了一步)
虽然Vista之后版本有进程创建回调函数的Ex版,而且Ex版可以拦截进程创建,
但是由于在Ex版回调函数内用第三个参数的最后一个元素来阻止进程创建的话,可能会出现弹框,所以不安全,所以这个方案可行性不高。
(这里说的不安全,是说可以被用户层看到这个弹框,可以被发现,处理麻烦,如果是用户自己设置的拦截,那么根本不需要通知用户,如果是我们自己做拦截,就不该让用户发现,
不管怎么说,这个弹框都是不应该出现的。)
所以,我想了这个方案,不知道是否可行,先纪录下这个方案。
    1:注册进程创建回调,以及镜像加载回调,普通版本就可以了,不需要Ex版,这样从XP开始的所有版本就都兼容了。
    2:当一个进程被创建的时候,进程创建回调会被调用,而且create参数应该为 1,
      这时,纪录进程的全部信息,保存在安全的位置(设备扩展),由于进程可能很多,所以需要用链表
      要保存的信息包括,进程ID,进程文件路径,以及一个进程创建标志flage,可以设置为0
    3:进程创建回调被调用之后,紧接着被调用的就是镜像加载回调,而第一个被加载的镜像,就是那个可执行文件,
      也就是说,当镜像加载回调被触发的时候,根据进程ID,去设备扩展里面的链表中找到这个进程ID,判断它的flage是否为0
      如果为0的话,修改flage为1,标志已经被处理过了(安全起见也可以判断镜像名字)
      镜像加载回调的第三个参数可以得到镜像基址,根据基址,然后分析一下PE,得到OEP的RVA,加上基址,得到VA,
      这里是重点,把VA的第一个字节数据记录下来,保存在链表中,然后修改VA的第一个字节为 C3 ,也就是 retn
      这样,可以保证,进程的主线程刚刚启动,就返回了
      为什么要保存VA的数据,这就是下面说的
      (一般来说,其实可以用类似 0x 这种默认的建议加载地址来做判断可执行文件的镜像基址的,
      但是这样做不安全,因为可执行文件也可以有重定向表,这样基址就是可变的了,所以还是需要用第一次加载的方式,来寻找可执行文件的镜像基址)
    4:由于执行进程创建回调、镜像加载回调的时候,镜像只是被映射到了内存,并不是被写入到内存中的,所以对内存的修改会直接影响到可执行文件
      这时,就要对原始文件做一个修复,
      修复的时机就是在进程退出的时候,也就是进程加载回调第二次被调用的时候,也就是create参数为0的时候,根据当前进程ID,去设备扩展里面寻找进程路径
      根据分析PE文件,得到OEP的RVA,然后找到它的位置,修改第一字节,第一字节是什么?前面已经记录下来了。
到此为止,一套使用进程回调来拦截进程的工作就完成了。
这只是个构想,不知道能否实现,准备验证一下。
阅读(...) 评论()温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
人生无数的坎坷在等着你,如果你无法跨越,那么你就无法前进
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(1460)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'CALLBACK回调函数使用之一',
blogAbstract:'&
凡是由你设计却由windows系统呼叫的函数,统称为callback函数。某些API函数要求以callback作为你参数之一。如SetTimer,LineDDA,EnumObjects。
回调函数是由开发者按照一定的原形进行定义的函数(每个回调函数都必须遵循这个原则来设计)
例如:----------------------------------------BOOL CALLBACK DialogProc(&&&&&&&&&& HWND hwndDlg, // handle of dialog box&',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:9,
publishTime:9,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'人生无数的坎坷在等着你,如果你无法跨越,那么你就无法前进',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}AppDelegate中几个常用回调函数的调用时机 - 简书
AppDelegate中几个常用回调函数的调用时机
由于AppDelegate中的回调函数非常多, 使用起来感觉很混乱, 不知道什么情况该用哪个回调函数. 于是百度+实测整理出来了一些常用回调函数的调用时机, 发出来做个笔记, 也供大家参考参考
– (void)applicationDidFinishLaunching:(UIApplication *)
当应用程序启动时(不包括已在后台的情况下转到前台),调用此回调。此方法基本已经弃用,改用第2个方法代替。
– (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchO
当应用程序启动时(不包括已在后台的情况下转到前台),调用此回调。launchOptions是启动参数,假如用户通过点击push通知启动本应用,这个参数里会存储一些push通知的信息。而如果用户通过其它应用或URL链接启动本应用(openURL), 则这个参数里会存储一些启动本应用的应用和URL的一些信息。
– (void)applicationDidBecomeActive:(UIApplication *)
当应用程序全新启动,或者在后台转到前台,完全激活时,都会调用这个方法。如果应用程序是以前运行在后台,这时可以选择刷新用户界面。
– (void)applicationWillResignActive:(UIApplication *)
当应用从活动状态主动到非活动状态的应用程序时会调用这个方法。这可导致产生某些类型的临时中断(如传入电话呼叫或SMS消息)。或者当用户退出应用程 序,它开始过渡到的背景状态。使用此方法可以暂停正在进行的任务,禁用定时器,降低OpenGL ES的帧速率。游戏应该使用这种方法来暂停游戏。
调用时机可能有以下几种:锁屏,按HOME键,下接状态栏,双击HOME键弹出低栏,等情况。
– (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)
这个方法已不再支持,可能会在以后某个版本中去掉。建议用下面第6个方法代替
– (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)
当用户通过其它应用启动本应用时,会回调这个方法,url参数是其它应用调用openURL:方法时传过来的。sourceApplication参数是打开本应用的应用的信息。
– (void)applicationDidReceiveMemoryWarning:(UIApplication *)
当应用可用内存不足时,会调用此方法,在这个方法中,应该尽量去清理可能释放的内存。如果实在不行,可能会被强行退出应用。
– (void)applicationWillTerminate:(UIApplication *)
当应用退出,并且进程即将结束时会调到这个方法,一般很少主动调到,更多是内存不足时是被迫调到的,我们应该在这个方法里做一些数据存储操作。
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken NS_AVAILABLE_IOS(3_0);
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error NS_AVAILABLE_IOS(3_0);
当客户端注册远程通知时,会回调上面两个方法。
如果成功,则回调第一个,客户端把deviceToken取出来发给服务端,push消息的时候要用。
如果失败了,则回调第二个,可以从error参数中看一下失败原因。
注:注册远程通知使用如下方法:
UIRemoteNotificationType t=UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeS
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:t];
– (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userI
当应用在前台运行中,收到远程通知时,会回调这个方法。
当应用在后台状态时,点击push消息启动应用,也会回调这个方法。
– (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)
当应用收到本地通知时会调这个方法,同上面一个方法类似。
如果在前台运行状态直接调用,如果在后台状态,点击通知启动时,也会回调这个方法
– (void)applicationDidEnterBackground:(UIApplication *)
当用户从台前状态转入后台时,调用此方法。使用此方法来释放资源共享,保存用户数据,无效计时器,并储存足够的应用程序状态信息的情况下被终止后,将应用 程序恢复到目前的状态。如果您的应用程序支持后台运行,这种方法被调用,否则调用applicationWillTerminate:用户退出。
– (void)applicationWillEnterForeground:(UIApplication *)
当应用在后台状态,将要进行动前台运行状态时,会调用此方法。
如果应用不在后台状态,而是直接启动,则不会回调此方法。
AppDelegate中几个常用的回调调用时机 ios 本篇文章主要介绍一些UIApplicationDelegate中几个常用的回调方法的调用时机。 以帮助你判断哪些方法倒底放到哪个回调中去实现。 1. – (void)applicationDidFinishLaunch...
本篇文章主要介绍一些UIApplicationDelegate中几个常用的回调方法的调用时机。 以帮助你判断哪些方法倒底放到哪个回调中去实现。 1. – (void)applicationDidFinishLaunching:(UIApplication *)applica...
本篇文章主要介绍一些UIApplicationDelegate中几个常用的回调方法的调用时机,以帮助你判断哪些方法倒底放到哪个回调中去实现 1. – (void)applicationDidFinishLaunching:(UIApplication *)applicati...
UIApplication深入研究 很多时候,我们不需要关心这个类,我们很少继承这个类,偶尔会调用这个类的api来实现一些功能,但是不可否认,这个类是iOS编程中很重要的一个概念,所以我这里写这个文章来总结以下这个类的信息,如果写的不对的地方,请留言,多谢。 UIAppli...
Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线)。分布式系统的协调导致了样板模式, 使用Spring Cloud开发人员可以快速地支持实现这些模式的服务和应用程序。他们将在任何分布式...
最近李健唱火了《父亲写的散文诗》这首歌,在一个安静的夜里,带着耳机,听着听着,眼泪便扑簌簌地往下掉。李健温柔又细腻的声音浅唱低吟的唱到了每一个人的心里,勾起了我们心中最柔软的那根弦。 我承认这是让自己落泪的第二首歌,第一首是筷子兄弟的《父亲》,它们充满着故事感和年代感,它们...
想和从前一样健谈理想 可惜生活是只流氓 我以为我的生活是背上行囊 如今我欠人生一场希望 在每个人静的夜晚 习惯性开始失眠 日子是一支香烟,想逃离却一直牵绊 没有人愿意与自己为敌 只是苟且迫不得已 岁月慢慢磨平的不止脾气 还有那件喜欢的军大衣 想要的也可以笑着放下 想说的也能...
清风透雨来, 伊人何处去, 莫道千百日, 花开只此时, 卿许我竹马, 我报之青梅, 此去山水北, 相思夜夜回, 来年池边柳, 执荷盼君归。
我真的不想再经历爱得很累的爱情。
腾讯云技术社区-简书主页持续为大家呈现云计算技术文章,欢迎大家关注! 前言之前有在虚拟机通过翻墙搭建了FBCTF平台,但是毕竟是虚拟机搭建的,只能在校园里网内使用,要让外网访问就需要做内网穿透了,麻烦而且不稳定,于是就想要在云服务器上搭建,由于开始思路就很正确,一次就成功了...博客访问: 5684072
博文数量: 770
博客积分: 2150
博客等级: 上尉
技术积分: 13141
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: C/C++
1. 什么是回调&
软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:
同步调用、回调和异步调用。
同步调用, 是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;
回调,& & &是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;
异步调用, 是一种类似消息或事件的机制,不过它的调用方向刚好相反,
& & & & & 接口的服务在收到某种讯息或发生某种事件时,会主动通知客户端(即调用客户端的接口)。
回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。
同步调用是三者当中最简单的,而回调又常常是异步调用的基础,
因此,下面我们着重讨论回调机制在不同软件架构中的实现。&
对于不同类型的语言(如结构化语言和对象语言)、平台(Win32、JDK)或构架(CORBA、DCOM、WebService),
客户和服务的交互除了同步方式以外,都需要具备一定的异步通知机制,
让服务方(或接口提供方)在某些情况下能够主动通知客户,而回调是实现异步的一个最简捷的途径。&
对于一般的结构化语言,可以通过回调函数来实现回调。
回调函数也是一个函数或过程,不过它是一个由调用方自己实现,供被调用方使用的特殊函数。&
在面向对象的语言中,回调则是通过接口或抽象类来实现的,
我们把实现这种接口的类成为回调类,回调类的对象成为回调对象。
对于象C++或Object Pascal这些兼容了过程特性的对象语言,不仅提供了回调对象、回调方法等特性,
也能兼容过程语言的回调函数机制。&
Windows平台的消息机制也可以看作是回调的一种应用,
我们通过系统提供的接口注册消息处理函数(即回调函数),从而实现接收、处理消息的目的。
由于Windows平台的API是用C语言来构建的,我们可以认为它也是回调函数的一个特例。&
对于分布式组件代理体系CORBA,异步处理有多种方式,如回调、事件服务、通知服务等。
事件服务和通知服务是CORBA用来处理异步消息的标准服务,他们主要负责消息的处理、派发、维护等工作。
对一些简单的异步处理过程,我们可以通过回调机制来实现。&
下面我们集中比较具有代表性的语言(C)和架构(C++)来分析回调的实现方式、具体作用等。&
2 过程语言中的回调(C)&
2.1 函数指针&
回调在C语言中是通过函数指针来实现的,通过将回调函数的地址传给被调函数从而实现回调。
因此,要实现回调,必须首先定义函数指针,请看下面的例子:&
void Func(char *s);// 函数原型
void (*pFunc) (char *);//函数指针
可以看出,函数的定义和函数指针的定义非常类似。&
一般的化,为了简化函数指针类型的变量定义,提高程序的可读性,我们需要把函数指针类型自定义一下。&
typedef void(*pcb)(char *);
回调函数可以象普通函数一样被程序调用,但是只有它被当作参数传递给被调函数时才能称作回调函数。&
被调函数的例子:
void GetCallBack(pcb callback)
& & /*do something*/
用户在调用上面的函数时,需要自己实现一个pcb类型的回调函数:
void fCallback(char *s)&
& & /* do something */
然后,就可以直接把fCallback当作一个变量传递给GetCallBack,
GetCallBack(fCallback);
如果赋了不同的值给该参数,那么调用者将调用不同地址的函数。
赋值可以发生在运行时,这样使你能实现动态绑定。&
2.2 参数传递规则&
到目前为止,我们只讨论了函数指针及回调而没有去注意ANSI C/C++的编译器规范。许多编译器有几种调用规范。
如在Visual C++中,可以在函数类型前加_cdecl,_stdcall或者_pascal来表示其调用规范(默认为_cdecl)。
C++ Builder也支持_fastcall调用规范。
调用规范影响编译器产生的给定函数名,参数传递的顺序(从右到左或从左到右),
堆栈清理责任(调用者或者被调用者)以及参数传递机制(堆栈,CPU寄存器等)。&
将调用规范看成是函数类型的一部分是很重要的;不能用不兼容的调用规范将地址赋值给函数指针。例如:&
// 被调用函数是以int为参数,以int为返回值
__stdcall int callee(int);&
// 调用函数以函数指针为参数
void caller( __cdecl int(*ptr)(int));&
// 在p中企图存储被调用函数地址的非法操作
__cdecl int(*p)(int) = // 出错, 前者是__cdecl ,后者是__stdcall
指针p和callee()的类型不兼容,因为它们有不同的调用规范。
因此不能将被调用者的地址赋值给指针p,尽管两者有相同的返回值和参数列&
2.3 应用举例&
C语言的标准库函数中很多地方就采用了回调函数来让用户定制处理过程。
如常用的快速排序函数、二分搜索函数等。&
快速排序函数原型:
void qsort(void *base, size_t nelem, size_t width,&
& & & & & & int (_USERENTRY *fcmp)(const void *, const void *));
二分搜索函数原型:
void *bsearch(const void *key, const void *base, size_t nelem,size_t width,&
& & & & & & int (_USERENTRY *fcmp)(const void *, const void *));
其中fcmp就是一个回调函数的变量。&
下面给出一个具体的例子:&
int sort_function( const void *a, const void *b);
int list[5] = { 54, 21, 11, 67, 22 };
int main(void)
& &qsort((void *)list, 5, sizeof(list[0]), sort_function);
& &for (x = 0; x < 5; x++)
& & & printf("%i\n", list[x]);
& &return 0;
int sort_function( const void *a, const void *b)
& &return *(int*)a-*(int*)b;
3 面向对象语言中的回调: Callback在C/C++中的实现
Callback是这样的一类对象(在这里不能简单的理解为"回调函数"了):
你注册一个函数,以及调用它时的参数,希望在满足某个条件时,以这些注册的函数调用这个回调,完成指定的操作.
很多地方会使用到这个概念.
比如,UI程序中,注册一个函数,当某个鼠标事件发生的时候自动调用;
比如,创建一个线程,线程开始运行时,执行注册的函数操作.
Callback的出现,本质上是因为很多操作都有异步化的需要---
你不知道它什么时候会执行,只需要告诉它,在执行的时候,调用我告诉你的操作即可.
尽管使用的地方不尽相同,但是从程序的角度上看,做的事情都是差不多的.
要实现一个Callback,最大的难点在于,变化的参数和需要统一的对外接口之间的矛盾.
也就是说,回调函数执行时参数的数量是你无法预知的.而你需要对外提供一个统一的接口,
调用该接口的不需要关注到注册进去的到底是什么,有几个参数,具体的执行留到回调真正执行的时候再去处理.
简单介绍一下目前我所知道的几种方法,有C++的,&
1) 使用模板&
将不同参数的类型,作为模板的参数.比如:
class Closure&
& & virtual ~Closure(){}&
& & virtual void Run() {}
protected:&
& & Closure(){}&
template class Callback0 : public Closure&
& & typedef void (T::*Done)();&
& & Callback0(T *obj, Done run) : object_(obj) , run_(run)&
& & virtual void Run()&
& & & & (object_->*run_)();&
& & T *& object_;&
& & Done run_;&
template class Callback1 : public Closure&
& & typedef void (T::*Done)(T1);&
& & Callback1(T *obj, Done run, T1 arg) : object_(obj)&
& & , run_(run)&
& & , arg0_(arg)&
& & virtual void Run()&
& & & & (object_->*run_)(arg0_);&
& & T *object_;&
& & Done run_;&
& & T1 arg0_;&
class Test&
& void Run0()&
& & printf("in Test::Run0/n");&
& void Run1(int i)&
& & printf("in Test::Run1/n");&
NewCallback(T *obj, void (T::*member)())&
& return new Callback0(obj, member);&
NewCallback(T *obj, void (T::*member)(T1), T1 P)&
& return new Callback1(obj, member, P);&
int main()&
& Closure *callback0 = NewCallback(&test, &Test::Run0);&
& callback0->Run();&
& delete callback0;
& Closure *callback1 = NewCallback(&test, &Test::Run1, 1);&
& callback1->Run();&
& delete callback1;
& return 0;&
在这里,定义了一个虚拟基类Closure,它对外暴露一个接口Run,
也就是,使用它的时候只需要使用Closure指针->Run即可以执行注册的操作.
需要注意的是,Closure的构造函数声明为protected,也就是仅可以被子类调用.&
接下来,定义的Closure'子类都是模板类,其中的模板都是参数,
我分别实现了两种子类,分别是不带参数的和带一个参数的.将回调函数需要的参数,保存在具体的子类对象中.&
最后,对外构造一个Closure指针时,最好也提供一致的接口,这里分别为两种子类实现了NewCallback函数.&
剩下的,理解起来应该不难.
这种实现方法,看明白的就知道,其实难点不多.
它将回调函数和传递给回调函数的参数放在了一个类中,当外部调用Run接口的时候,再根据内部的实现来具体进行操作.&
但是,我本人很不喜欢模板满天飞的代码,所以应该还有些别的方法来实现吧?
2) 不使用模板,将参数和回调分离,分别对参数和回调进行抽象&
CEGUI是一款开源的游戏UI项目,早几年我还在做着3D引擎程序员梦的时候,曾经看过一些,对它的一些代码还有些印象.&
里面对UI事件的处理,也使用了类似Callback的机制(这种使用场景最开始的时候曾经说过,所以应该不会感到意外).&
在CEGUI中,一个事件由一个虚拟基类Event定义,处理事件的时候调用的是它的纯虚函数fireEvent,
而这个函数的参数之一是EventArgs--这又是一个虚拟基类.&
所以,熟悉面向对象的人,应该可以很快的反应过来了:
在Event的子类中实现fireEvent,而不同的函数参数,可以从EventArgs虚拟基类中派生出来.&
于是,具体回调的时候,仅仅需要调用 Event类指针->fireEvent(EventArgs类指针)就可以了.&
(我在这里对CEGUI的讲解,省略了很多细节,仅仅关注到最关注的点,感兴趣的可以自己去看看代码)
对比1)和2)两种解决方法,显然对我这样不喜欢模板的人来说,更喜欢2).
除了模板的代码读起来比较头大,以及模板会让代码量增大之外.
喜欢2)的原因还在于,C对"类模板"机制的支持实在是欠缺,至今除了使用宏之外,
似乎找不到很好的办法能够实现类C++的模板机制.
但是,如果采用2)的继承接口的方式,C就可以很清楚的实现出来.所以就有了下面C的实现:
3) C的实现.&
有了2)的准备,使用C来实现一个类似的功能,应该很容易了,下面贴代码,应该很清楚的:
#include &
#include &
typedef struct event&
& void (*fireEvent)(void *arg);&
typedef struct event_arg1&
}event_arg1_t;
void fireEvent_arg1(void *arg)&
& event_arg1_t *arg1 = (event_arg1_t*)
& printf("arg 1 = %d/n", arg1->value);&
#define NewEvent(event, eventtype, callback)& & & /&
& do {& & & & & & & & & & & & & & & & & & & & & & /&
& & & *(event) = (event_t*)malloc(sizeof(event_t)); /&
& & & assert(*(event));& & & & & & & & & & & & & & & /&
& & & (*(event))->arg = (eventtype*)malloc(sizeof(char) * sizeof(eventtype)); /&
& & & assert((*(event))->arg);& & & & & & & & & & & & &/&
& & & (*(event))->fireEvent =& & & & & & &/&
& } while (0)
#define DestroyEvent(event)& & & & & & & & & & & &/&
& do {& & & & & & & & & & & & & & & & & & & & & & /&
& & free((*(event))->arg);& & & & & & & & & & & & /&
& & free(*(event));& & & & & & & & & & & & & & & &/&
& } while(0)& & &
int main()&
& event_t *
& NewEvent(&event, event_arg1_t, fireEvent_arg1);&
& ((event_arg1_t*)(event->arg))->value = 100;&
& event->fireEvent(event->arg);
& DestroyEvent(&event);
& return 0;&
阅读(50) | 评论(0) | 转发(0) |
下一篇:没有了
相关热门文章
给主人留下些什么吧!~~
请登录后评论。

我要回帖

更多关于 python 回调函数 使用 的文章

 

随机推荐