Skip to content

关于 C_RtmEventHandlerBridge #6

Open
@Lensual

Description

@Lensual

我看到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都不给吗)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions