纠纷奇闻作文社交美文家庭
聚热点
家庭城市
爱好生活
创业男女
能力餐饮
美文职业
心理周易
母婴奇趣
两性技能
社交传统
新闻范文
工作个人
思考社会
作文职场
家居中考
兴趣安全
解密魅力
奇闻笑话
写作笔记
阅读企业
饮食时事
纠纷案例
初中历史
说说童话
乐趣治疗

FFI实战之对接GO(CGO)(二)

8月24日 游鱼坊投稿
  简章入题
  上一篇,咱们讲过了GO与FFI的基本知识,包括如何让GO和C语言互相调用,以及常规的一些变量如何通过构造相同的结构类型来进行转换,以此来达到咱们的目的,然后在很多时候,咱们不仅仅是调用函数,还需要一些更能打通双方的操作
  比如说,我们用GO写了一个动态库,去给C语言用,而这个动态库中会不断的去接收一些状态,然后状态变更了,就通知到C语言,让C语言去执行,当然这里的方法比较多,比如说用Socket,用消息等等等,但是这些用在进程内通讯就有点大材小用了,所以我们首要考量的就是咱们需要在合适的时候去获取C语言的某一个函数去执行
  很多人可能就说,那简单啊,上一篇讲过了,咱们在C语言中写一个函数导出来,然后GO语言不就能用了吗,确实是的啊,但是,如果说此时这个GO的库是别人写的一个共有库,是给你用的,此时,别人根本不知道你的导出函数是啥子,所以,这个时候,咱们的回调函数就要上线了,就是双方协商一个函数声明原型,但是咱们不去实现他,只要要使用的人,实现一个跟这个函数申明一样的函数,就能将这个函数传递给需要调用的地方,然后需要的时候,就直接使用这个函数指针来进行调用,这就是函数回调了,函数的真实实现在C中,调用这个函数在GO中,实际上原理和上一篇的一样,只是上一篇,咱们是直接使用的导出函数去执行,现在是咱们这个函数不会导出去,因为不同的人可能实现不同的函数功能,咱们用别人的库,传递过去的是函数的指针。初步分析
  首先,我们先明确两个目标,要传递一个函数指针,那么首先,我们需要搞一个相同的函数声明,如何来声明这个回调的函数类型呢,在哪里声明。
  抓到问题了,咱们就专门针对性的去思考就行,那么首先,我们直接将函数原型类型声明在GO代码中行不行呢,思考一下:在GO语言中,函数本身是一等公民和其他类型一样,并无不同,是可以作为变量传递的,且先不说GO函数原型的ABI是否和C的一样,另外一个最主要的是GO的函数传参方式,Go1。17之后,X86平台下传参方式是使用fastcall方式,也就是寄存器先用,和咱们的stdcall,cdecl都不一样,具体的,可以去看看GO反射调用函数的里面的函数调用相关的代码(也就是Value。Call的代码),里面有明确的标记当前函数的调用方式(如abiStepStack等)。
  从以上猜想上面我们就可以知道GO函数原型并不是一个CABI函数原型,而在Go语言中,要将一个Go的函数类型转到一个和其他语言通用的函数指针原型类型就需要使用syscall。NewCallback函数或者NewCallbackCDecl函数,这两个函数主要就是表示调用方式不同,一个是stdcall,还有一个是cdecl,可以查看这两个函数,实际上调用的都是compileCallback,而compileCallbac的第一个参数是Go函数,第二个参数,就是之前我们在上一篇讲过的了
  stdcall是在函数自身清理堆栈,咱们在Windows中最常见,也就是基本上,如果函数有几个参数的话,函数调用结束之后,会跟上一个retXXX这类指令来平堆栈,而Cdecl的函数在函数执行完了之后,函数本身并不会有一个retXXX的函数,反而会是在调用这个函数的函数中也就是callXX这个函数之后会产生一个AddESP,XXX的指令来平栈,至于为啥要设计成这样,主要原因就是cdecl需要支持那种不知道需要传递多少个参数的函数(比如printf函数),所以函数自身无法知道要平的堆栈的大小,只有调用方知道有多少个参数,所以只能由调用方来平栈,其实基本上就是之前上一篇讲过的,具体的可以自行查看相关的反汇编代码,这里不再详诉了,哎,关于这方面一下子又说多了,这块如果没有相关的知识,可能比较糊涂,没关系,咱们记住就好。
  从上面的分析,所以如果要在Go中定义一个回调函数,给外面的语言使用,如果要直接使用Go语言自身的方式的话,就必须使用syscall。NewCallback或者NewCallbackCDecl来将函数声明包一包,然后才能是通用的CABI,比如typegoCallBackNotifyfunc(string2C。pgoString)intvarmbgoCallBackNotifysyscall。NewCallback(mb)
  类似于这种,包过之后才能是一个有效的CABI,而这个是没有啥意义的,就搞一个原型,也没必要搞那么复杂,所以我们直接将回调函数的原型声明在CGO区。这样就保障了ABI通用,是最简单的,也最明了的了。比如上面声明为includestdio。hincludestdlib。hincludestring。htypedefstructgoString{charutf8D}goString,pgoStypedefintstdcall(notifyCallBack)(pgoStringstring);importC
  这个时候就有了一个回调函数原型,并且指定了调用方式为stdcall将C函数指针传递到go
  回调函数原型咱们已经定义好了,现在咱们要做的如何将一个外部的函数传递到Go中来,然后让Go可以调用这个外部函数,怎么传呢,函数指针,咱们直接使用uintptr作为参数来表示函数指针就行。那么来了varnotifyCallBackuintptrexportregisterCallBackfuncregisterCallBack(callBackFuncuintptr){notifyCallBackcallBackFunc}
  上面搞了一个全局变量notifyCallBack,使用这个来保存注册的回调函数,以便于后续咱们在go中来调用这个全局函数;到这里,注册写好了,那么下面我们需要在C语言中写一个函数,用这个C函数作为回调函数,然后在Go中来调用这个回调函数,也就是上面的notifyCallBackincludestdio。hincludestdlib。hincludestring。htypedefstructgoString{charutf8D}goString,pgoStypedefintstdcall(notifyCallBack)(pgoStringstring);外部语言定义的回调函数NotifyMsgstaticintstdcallNotifyMsg(pgoStringdata){charnData〔datadatalen1〕;nData〔datadatalen〕0;memcpy(nData,datautf8Data,datadatalen);printf(recvfromgo:s,End,nData);return0;}这里用来调用回调函数staticvoidcallNotify(voidnotifyFunc,pgoStringstring){((notifyCallBack)notifyFunc)(string);}staticvoidinit(){registerCallBack(NotifyMsg);}importC
  好,这里基本上,我们就算是定义模拟了一个外部函数的调用环境。
  然后现在咱们做一个在Go中模拟调用这个环境的import(fmtunsafe)这个就是在GO中模拟调用上面的回调函数funcnotify(msgstring){C。callNotify(unsafe。Pointer(notifyCallBack),C。pgoString(unsafe。Pointer(msg)))}funcmain(){C。init()notify(thisisfromGo)}
  此时,go中的notify函数就是对于C语言中的回调函数NotifyMsg的包装了。这个写法算是比较明白的,是在CGO内部写了一个回调函数的调用跳板函数C。callNotify来实现了和回调函数的对接。
  那么如果不使用跳板函数的话,能不能实现调用这个回调函数呢?大家可以思考一下,咱们下回分解
投诉 评论 转载

任天堂回应Wii和DSi商店关闭正在进行维护IT之家3月23日消息,上周,有网友声称任天堂的Wii和DSi商店至少从3月16日就已经关闭,在网上引起讨论,但任天堂一直没有回应,自然而然也就引发了人们对这两代产品命运的担忧……ARPU重回50元,单用户收入迎历史性反弹,中国移动迎来第二近日,中国的几家运营商相继发布前三季度财报,都相当不错。财报数据显示,2021年前三季度,中国移动经营业绩全面向好,营运收入达到6486亿元,同比增长12。9;股东应占利……游戏中出现狙击玩家并威胁牟利的恶意行为,和平精英官方回应IT之家4月9日消息,今日,《和平精英》官方发布公告称,近期接到举报称,游戏内出现了以定向狙击等方式威胁他人并牟取不当利益的行为。公告指出,该类行为严重破坏玩家们的正常游……FFI实战之对接GO(CGO)(二)简章入题上一篇,咱们讲过了GO与FFI的基本知识,包括如何让GO和C语言互相调用,以及常规的一些变量如何通过构造相同的结构类型来进行转换,以此来达到咱们的目的,然后在很多……如果地球脱水了会是什么姿势?地球上全部水变成水球有多大?假定地球有一天失掉了大气层,没有大气层的保护,太阳辐射和热量会导致海水蒸发殆尽,生灵灭绝,万物成灰,那么一个干燥凄凉的地球就会呈现出来,会是什么姿势呢?300年前的科学幻……畅享短视频娱乐,移动重磅福利来袭随着网络的不断发展,现在人们获取信息的方式发生了很多改变,网络让我们的生活变得更加丰富,让我们没有了枯燥无味的生活。相信很多人都有看短视频的习惯,利用短视频可以很好的消遣娱乐,……光环改编真人剧集发布正式预告将于3月24日上线,CortanIT之家1月31日消息,HaloTheSeries官方公布了《光环》改编真人剧集的正式预告片,并宣布开播日期:3月24日上线Paramount。预告片中展示了剧集的角色,……Xbox金会员本周末免费游戏公布Control上古卷轴OL模IT之家4月14日消息,Xbox免费游戏日再次回归,XboxGamePassUltimate和XboxLiveGold订阅者本周末可以免费玩《控制》、《模拟狩猎2》和《上古卷轴……懒出来的财富阿里巴巴总裁马云一直说自己是个懒人,说世界上很多超级富翁都是懒人。电梯的出现是因为懒得爬楼,汽车的出现是因为懒得走路,唱片的出现是因为懒得听音乐会马云的懒不是傻懒,他懒出了思路……Xbox现支持用手柄切换电视输入信号,无需遥控器IT之家4月7日消息,对于市面上大多数的电视型号而言,切换输入信号往往需要遥控器或电视机身按键。从今天开始,XboxSeriesXS用户可以使用手柄进行电视输入信号切换了。……小岛秀夫被员工吐槽观念过时反战游戏已经过气了,现在是魔法战斗IT之家2月14日消息,《合金装备》和《死亡搁浅》的游戏制作人小岛秀夫近日称,自己被员工吐槽游戏观念过时。他在推特中表示,员工称反战、反核题材游戏已经是明日黄花了,现在是……小岛秀夫晒新企画文件夹,暗示正在开发游戏新作IT之家1月12日消息,日本游戏制作人小岛秀夫今日在推特晒图,Mac电脑桌面上放着一个名为新企画的文件夹,暗示正在开发游戏新作。不过,小岛秀夫除了这张图一句话都没说,我们……
怎么查手机通话记录(怎么查通话录音记录)河南省移动社会渠道(移动社会渠道如何转型)河南农村穷女孩,练武术20年,爆火后登上央视,年入100万,海南石花水洞地质公园国家4A级旅游景区今天正式揭牌看祖国好风光中国农村改革发源地凤阳小岗村租赁大事记(6。287。5)危险的西藏穷游,为何却总是让人心驰神往?山东最大面积香草主题观光园就在济南,其实还有很多你不知道!达州领克01PHEV可试乘,降价2。25许多人都在问什么时候才可以到什么国家什么地方旅遊呀?宾利也玩插混,保时捷和宾利你选谁,网友保时捷土鳖!夜来红烛暖炊烟袅农家隆冬时节东北游之梦幻雪乡
适度放松政策才能激活货币存量风起香江潮涌中原热议聚热点网 大理云龙旅游:四个地方,不容错过!(附超详细攻略)热传聚热点 世界大众点评口红第四名(YvesSaintLaurent圣罗企业如何打造组织智慧?历史东汉和刘邦有关系吗儿童最易被忽视的咳嗽有哪两种广东省运会自行车比赛拉开战幕115名选手逐鹿公路项目年车龄的发动机到底多脏拆给你看跟着小米去找“猪”,顺为帮雷军一年拿下8个IPO铠甲勇士猎铠黎明天塔真的是最后一部吗?热闻聚热点网 吴君如终于认真打扮,葫芦身材抢镜,吊带裙清新减龄

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找美丽时装彩妆资讯历史明星乐活安卓数码常识驾车健康苹果问答网络发型电视车载室内电影游戏科学音乐整形