需求来源
Open-IM 是由前微信技术专家打造的全开源、永久免费、无限制的即时通讯组件。Open-IM 包括 IM 服务端和客户端 SDK,实现了高性能、轻量级、易扩展等重要特性。开发者通过集成 Open-IM 组件,并私有化部署服务端,可以将即时通讯、实时网络能力免费、快速集成到自身应用中,并确保业务数据的安全性和私密性。
OpenIM包括Server和SDK,两者都是采用golang实现的,移动端通过gomobile生成代码,再加上对应的插件,这样能适应多个前端开发框架,无论是原生的iOS、Android还是跨端开发的Flutter、uniapp、react native、cordova等。OpenIM SDK 要用在pc端electron框架中,先解决C调用golang的问题,再打通nodejs调用C /C++,当然这里还涉及到各种回调函数。
网上有很多例子告诉你怎么从Go语言调用C /C++语言的函数,但少文章有告诉你,如何从C /C++语言函数中调用Golang语言写的函数。本文通过实际代码,来展示两个能力:(1)golang如何编译成动态库so (2)C /C++如何调用golang函数 (3)golang如何调用C /C++的回调函数。
goland代码及注意事项
a.go代码:
在代码块,有几个点需要注意:
(1)package main 这个必须是main
(2)这个注释不能少,原封不动复制粘贴即可
/* #cgo CFLAGS: -I . #include <stdio.h> #include <string.h> #include <stdlib.h> typedef void (*callback)(void *,int); extern void c_callback (void *,int); extern callback _cb; */
(3)对于提供给C调用的函数,在函数上一行加上export 例如://export doSomethingCallback
(4) main函数保留
func main() { }
b.go代码
原封不动保存就可以了。
编译成动态库
生成libcallback.h 和libcallback.so
C代码调用
编译
生成可执行程序 m
输入./m 执行,C调用golang的doSomethingCallback函数,并在此函数回调C的gocallback函数,完成了C->golang->C
小节
C和golang互调能力打通,这样,对于采用C/C++开发的项目,如果某些业务特性不追求性能上的机制,可以通过golang实现,这样达到了开发效率和执行效率的平衡,对业务开发非常有帮助。
通过深度调用机制分析,无论是Go调用C,还是C调用Go,其需要解决的核心问题其实都是提供一个C/Go的运行环境来执行相应的代码。Go的代码执行环境就是goroutine以及Go的runtime,而C的执行环境需要一个不使用分段的栈,并且执行C代码的goroutine需要暂时地脱离调度器的管理。
要达到这些要求,运行时提供的支持就是切换栈,以及runtime.entersyscall。在Go中调用C函数时,runtime.cgocall中调用entersyscall脱离调度器管理。runtime.asmcgocall切换到m的g0栈,于是得到C的运行环境。在C中调用Go函数时,crosscall2解决gcc编译到6c编译之间的调用协议问题。cgocallback切换回goroutine栈。runtime.cgocallbackg中调用exitsyscall恢复Go的运行环境
OpenIMgithub开源地址:
更多技术文章:
开源OpenIM:高性能、可伸缩、易扩展的即时通讯架构 https://forum.rentsoft.cn/thread/3
【OpenIM原创】简单轻松入门 一文讲解WebRTC实现1对1音视频通信原理 https://forum.rentsoft.cn/thread/4
【OpenIM原创】开源OpenIM:轻量、高效、实时、可靠、低成本的消息模型 https://forum.rentsoft.cn/thread/1