编写你的应用程序(二)、原生客户端模块

原文链接:https://developer.chrome.com/native-client/devguide/coding/native-client-modules

注意:已针对ChromeOS以外的平台公布了此处所述技术的弃用。
请访问我们的 迁移指南 了解详情。


原生客户端模块

本文档介绍了在Native Client模块中实现的类和功能,以便Chrome加载,初始化和运行它。无论模块是否使用PNaCl,要求都是相同的,但取决于模块是用C还是C ++编写的。

介绍

Native Client模块没有main()功能。加载模块时,Native Client运行时调用模块中的代码来创建实例并初始化模块使用的API的接口。此初始化序列取决于模块是用C还是C ++编写的,并且要求您在每种情况下都实现特定的功能。

用C语言编写模块

C API使用前缀约定来显示接口是在浏览器中还是在模块中实现。以PPB_(可以读作“Pepper 浏览器 ”)开头的接口在浏览器中实现,并从模块中调用它们。以PPP_(“Pepper 插件 ”)开头的接口在模块中实现; 它们从浏览器调用,并将在模块实例的主线程上执行。

在C中实现Native Client模块时,必须包含以下组件:

  • 功能PPP_InitializeModulePPP_GetInterface
  • 实现接口PPP_Instance和模块使用的任何其他C接口的代码

对于每个PPP接口,您必须实现其所有功能,创建浏览器调用接口的结构,并确保该函数PPP_GetInterface返回接口的相应结构。

对于每个PPB接口,您必须声明一个指向该接口的指针,并通过调用get_browserinside 来初始化该指针PPP_InitializeModule

这些步骤在下面的代码摘录中说明,它显示了所需PPP_Instance 接口的实现和初始化。代码摘录还显示了三个不需要的其他接口的初始化:( PPB_InstanceNative Client模块通过它回调到浏览器)PPB_InputEventPPP_InputEvent

#include <stdlib.h>
#include <string.h>
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppp.h"
// Include the interface headers.
// PPB APIs describe calls from the module to the browser.
// PPP APIs describe calls from the browser to the functions defined in your module.
#include "ppapi/c/ppb_instance.h"
#include "ppapi/c/ppp_instance.h"
#include "ppapi/c/ppb_input_event.h"
#include "ppapi/c/ppp_input_event.h"

// Create pointers for each PPB interface that your module uses.
static PPB_Instance* ppb_instance_interface = NULL;
static PPB_InputEvent* ppb_input_event_interface = NULL;

// Define all the functions for each PPP interface that your module uses.
// Here is a stub for the first function in PPP_Instance.
static PP_Bool Instance_DidCreate(PP_Instance instance,
                                  uint32_t argc,
                                  const char* argn[],
                                  const char* argv[]) {
        return PP_TRUE;
}
// ... more API functions ...

// Define PPP_GetInterface.
// This function should return a non-NULL value for every interface you are using.
// The string for the name of the interface is defined in the interface's header file.
// The browser calls this function to get pointers to the interfaces that your module implements.
PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
        // Create structs for each PPP interface.
        // Assign the interface functions to the data fields.
         if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
                static PPP_Instance instance_interface = {
                        &Instance_DidCreate,
                        // The definitions of these functions are not shown
                        &Instance_DidDestroy,
                        &Instance_DidChangeView,
                        &Instance_DidChangeFocus,
                        &Instance_HandleDocumentLoad
                };
                return &instance_interface;
         }

         if (strcmp(interface_name, PPP_INPUT_EVENT_INTERFACE) == 0) {
                static PPP_InputEvent input_interface = {
                        // The definition of this function is not shown.
                        &Instance_HandleInput,
                };
                return &input_interface;
         }
         // Return NULL for interfaces that you do not implement.
         return NULL;
}

// Define PPP_InitializeModule, the entry point of your module.
// Retrieve the API for the browser-side (PPB) interfaces you will use.
PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id, PPB_GetInterface get_browser) {
        ppb_instance_interface = (PPB_Instance*)(get_browser(PPB_INSTANCE_INTERFACE));
        ppb_input_event_interface = (PPB_InputEvent*)(get_browser(PPB_INPUT_EVENT_INTERFACE));
        return PP_OK;
}

用C ++编写模块

在C ++中实现Native Client模块时,必须包含以下组件:

  • 工厂功能叫 CreateModule()
  • 定义自己的Module类的代码(派生自pp::Module 类)
  • 定义自己的Instance类的代码(派生自pp:Instance 类)

在“Hello tutorial”示例中(在NaCl SDK 的getting_started/part1目录中),这三个组件在文件中指定hello_tutorial.cc。这是工厂功能:

namespace pp {
  Module* CreateModule() {
    return new HelloTutorialModule();
  }
}

CreateModule()工厂函数是一个模块和浏览器之间的主绑定点,并作为进入点的模块。CreateModule()首次加载模块时,浏览器会调用; 此函数返回从pp::Module类派生的Module对象。浏览器保留Module对象的单个。

下面是“Hello tutorial”示例中的Module类:

class HelloTutorialModule : public pp::Module {
 public:
  HelloTutorialModule() : pp::Module() {}
  virtual ~HelloTutorialModule() {}

  virtual pp::Instance* CreateInstance(PP_Instance instance) {
    return new HelloTutorialInstance(instance);
  }
};

Module类必须包含一个CreateInstance()方法。浏览器CreateInstance()每次遇到<embed>引用同一模块的网页上的元素时都会调用该方法。该CreateInstance()函数创建并返回从pp::Instance类派生的Instance对象。

下面是“Hello tutorial”示例中的Instance类:

class HelloTutorialInstance : public pp::Instance {
 public:
  explicit HelloTutorialInstance(PP_Instance instance) : pp::Instance(instance) {}
  virtual ~HelloTutorialInstance() {}

  virtual void HandleMessage(const pp::Var& var_message) {}
};

如上例所示,模块的Instance类可能包含HandleMessage()函数的实现。HandleMessage()每次应用程序中的JavaScript代码调用postMessage()向实例发送消息时,浏览器都会调用实例的函数。有关如何在JavaScript代码和Native Client模块之间发送消息的详细信息,请参阅 Native Client消息传递系统

虽然Native Client应用程序需要CreateModule()工厂函数,Module类和 Instance类,但上面显示的代码示例实际上并不执行任何操作。开发人员指南中的后续文档以这些代码示例为基础,并添加了更多有趣的功能。

CC-By 3.0许可下提供的内容

猜你喜欢

转载自blog.csdn.net/y601500359/article/details/81179396
今日推荐