Description
我看到README中
- 所有的void 都用handle来定义,不要定义各种不同的c_Ixx ,太难理解了
- 将bridge 迁移到agora,不需要bridage,并修改main.go
我来澄清一下为什么会有这个 C_RtmEventHandlerBridge
首先在 RTM C++ SDK 中,RtmEventHandler
类中的回调皆以virtual方法实现。这就需要用C++来实现一个Bridge类 并公开为C的头文件,除非修改原始的C++ SDK。这一点对C/C++开发者来说应该很容易理解。
C SDK中的 C_IAgoraRtmClient.h
/**
* Occurs when receive a message.
*
* @param event details of message event.
*/
void C_IRtmEventHandler_onMessageEvent(C_IRtmEventHandler *this_, const struct C_MessageEvent *event);
C SDK中的 bridge/C_IAgoraRtmClient.h
/**
* Occurs when receive a message.
*
* @param event details of message event.
*/
typedef void (*C_RtmEventHandlerBridge_onMessageEvent)(C_RtmEventHandlerBridge *this_, void *userData,
const struct C_MessageEvent *event);
Q:这两个为什么如此的像
A:外面目录的是对官方C++ SDK的翻译,bridge
目录的是C->C++的桥接器,在之前项目中我将这两部分开来实现 (因为考虑到C++ SDK某些时候的形参可能是C++ SDK的对象,而不是CBridge,这不是一回事) ,但这也的确增加了复杂性。
Q:C_IRtmEventHandler *this_
是怎么回事
A:这是在模仿 C++ OOP
Q:void *userData
是怎么回事
A:这个变量的动机是CGO的机制(如果想让C来调用Go的函数,go需要编写一个静态函数,并且用//export来暴露他),导致无法OOP,go这边静态函数会找不到对应的类实例。
A2: 我的解决方案是使用一个userData指针存入到CBridge里,在所有handler上带上他。这一点我是借鉴ffmpeg的。
A3:再后来我有看到声网开放的RTC Server Go SDK使用了sync.Map解决的。我也想到过这一点,但我并不想查表,因为我不想去管理他。
此外既然选择了不公开 CBridge 的实现,bridge/RtmEventHandlerBridge.hh
是可以不暴露的
以上,希望可以帮助理解SDK源码
我看TODO list的一些其他问题(例如如何管理对象生命周期,既然是Go SDK,是否应该实现某些对象的自动声明周期管理?callback中是否需要帮助copy对象?),其实和我在编写SDK时候的困惑是相似的,我很想有人能跟我讨论一下如何实现是最佳的。当初编写SDK并没有太过仔细,的确存在很多问题,也没有做记录。
现在官方接手了SDK希望可以对一些实现方案做出设计选择,我很乐意为此贡献代码。
( https://github.com/Lensual/agora_rtm_sdk_cgo 连个star都不给吗)