PPAPI与Browser间使用AsyncIPC通信

Posted foruok

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PPAPI与Browser间使用AsyncIPC通信相关的知识,希望对你有一定的参考价值。

采用AsyncIpc这个项目(https://github.com/hicdre/AsyncIpc),来完成PPAPI Plugin进程与Browser进程的通信。

foruok原创,如需转载请关注foruok的微信订阅号“程序视界”联系foruok。

AsyncIpc的IPC实现基于管道,是参考Chromium的IPC代码而来,适用于Windows。Chromium在Render和Browser进程间就使用类似的IPC机制,每一个Render都会与Browser建立一个双向的Channel。AsyncIpc采用类似的概念,抽象了Channel用于进程间通信。

基本用法

介绍下怎么集成AsyncIpc以及关键的类库。

引入方式

AsyncIpc可以编译为静态库和动态库。根据需要,也可以直接把源码加入到项目中。

类库

AyncIpc定义了一个名字空间IPC。IPC::EndPoint代表一个接入点,使用时需要创建一个接入点。当有对端进程接入时,EndPoint会发送一些通知,这些通知通过IPC::Listener接口发送,所以,实现Listener接口即可。

EndPoint类的构造函数原型如下:

Endpoint(const std::string& name, Listener* listener, bool start_now);

它需要一个Listener,所以我们需要先实现Listener接口。IPC::Listener定义如下:

class Listener {
 public:
  // Called when a message is received.  Returns true iff the message was
  // handled.
  virtual bool OnMessageReceived(Message* message) = 0;

  // Called when the channel is connected and we have received the internal
  // Hello message from the peer.
  virtual void OnChannelConnected(int32 peer_pid) {}

  // Called when an error is detected that causes the channel to close.
  // This method is not called when a channel is closed normally.
  virtual void OnChannelError() {}

 protected:
  virtual ~Listener() {}
};

我们从Listener派生的类,实现OnMessageReceived、OnChannelConnected、OnChannelError三个方法即可处理IPC消息和状态。

那现在我们只需要一行代码就可以创建一个接入点等待连接了:

m_endPoint = new IPC::Endpoint("ppapi_ipc", this);

注意this指针代表的类实现了IPC::Listener接口,类声明如下:

class IPCImageClient : public IPC::Listener
{
public:
    IPCImageClient();
    virtual bool OnMessageReceived(IPC::Message* msg);

    virtual void OnChannelConnected(int32 peer_pid);

    virtual void OnChannelError();

private:
    void SendRawImage();
    void SendDecodedImage();

protected:
    int m_peerPid;
    IPC::Endpoint *m_endPoint;
};

而发送消息、接收或处理消息,就要用到Message类。发送消息的代码类似下面:

    scoped_ref_ptr<IPC::Message> msg(new IPC::Message(GetCurrentProcessId(), 101, (IPC::Message::PriorityValue)0));
    msg->WriteBytes(data, size);
    m_endPoint->Send(msg.get());

接收消息的代码类似这样:

bool IPCImageClient::OnMessageReceived(IPC::Message* msg)
{
    uint32 type = msg->type();
    switch (type)
    {
    case 1: // data was consumed,write again
        OutputDebugString(_T("SendImage to plugin\\r\\n"));
        SendDecodedImage();
        break;
    }
    return true;
}

或者这样:

bool IPCSimpleClient::OnMessageReceived(IPC::Message* msg)
{
    const void *data = msg->payload();;
    unsigned int len = msg->payload_size();
    UIImage *imageView = (UIImage*)m_view;
    uint32 type = msg->type();
    switch (type)
    {
    case 100: // decoded image data
        {
            OutputDebugString(_T("received decoded image\\r\\n"));
            SkBitmap received;
            SkImageInfo info = SkImageInfo::Make(1280, 720, 
                kBGRA_8888_SkColorType, kPremul_SkAlphaType, 
                kLinear_SkColorProfileType);
            received.installPixels(info, (void*)data, info.minRowBytes());
            imageView->cloneBitmapFrom(received);
            imageView->requestPaint(NULL);
        }
    break;
    ...
    }
}

总结一下,使用AsyncIpc的步骤如下:

  • 实现IPC::Listener接口
  • 创建IPC::EndPoint对象,传递Listener接口给它
  • 当连接建立后,发送消息(可以在OnChannelConnected方法中)
  • 在Listener::OnMessageReceived方法中处理消息

就这样吧。

其他参考文章:

以上是关于PPAPI与Browser间使用AsyncIPC通信的主要内容,如果未能解决你的问题,请参考以下文章

PPAPI插件与浏览器的通信

CEF中Browser进程与Render进程间通信

PPAPI+Skia实现的涂鸦板

PPAPI插件的动态创建改动删除

PPAPI中使用OpenGL ES绘图

PPAPI插件的动态创建修改删除