这份文档描述了:为使Chrome加载,初始化和运行Native Client模块,你需要为它实现的类和方法。无论模块是否使用PNaCl,依赖都是一样的,只取决于模块是用C还是C++编写的。
介绍
Native Client模块不需要main()函数。当模块加载时,Native Client运行时调用模块中的代码来创建一个实例并且初始化模块要使用的接口。这个初始化过程取决于模块是用C还是C++编写的,并且要求你为两种情况实现特定的函数。
C API使用一个前缀约定来表示一个接口是在浏览器还是模块中实现的。PPB_开头的接口(可以读作"Pepper browser")是在浏览器中实现的,从你的模块中调用。PPP_开头的接口("Pepper plugin")是在模块中实现的,从浏览器中调用并且在模块实例的主线程中执行。
用C编写模块
当你用C实现一个Native Client模块时必须包含这些组件:
PPP_InitializeModule函数和PPP_GetInterface函数。
实现PPP_Instance接口的代码和所有你的模块用到的其他接口。
对于每个PPP接口,你必须实现它所有的函数,创建浏览器调用接口所用的结构体,并确保PPP_GetInterface函数返回接口相应的结构体。
对于每个PPB接口,你必须定义一个指向接口的指针,并在PPP_InitializeModule中通过调用get_browser来初始化指针。
下面摘录的代码说明了这些步骤,代码演示了实现和初始化所必需的PPP_Instance接口。摘录代码同样演示了初始化三个额外的不必需的接口:PPB_Instance(Native Client模块通过它回调浏览器)和PPB_InputEvent和PPP_InputEvent。
#include <stdlib.h> #include <string.h> #include "ppapi/c/pp_errors.h" #include "ppapi/c/ppp.h" // 引入头文件. // PPB APIs 描述了从模块到浏览器的调用. // PPP APIs 描述了从浏览器到你的模块定义的函数的调用. #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" // 为你的模块使用的每个PPB接口创建指针. static PPB_Instance* ppb_instance_interface = NULL; static PPB_InputEvent* ppb_input_event_interface = NULL; // 为你的模块使用的每个PPP接口定义函数. // 这是PPP_Instance中第一个函数的存根(Stub). static PP_Bool Instance_DidCreate(PP_Instance instance, uint32_t argc, const char* argn[], const char* argv[]) { return PP_TRUE; } // ... 其他API函数 ... // 定义 PPP_GetInterface. // 这个函数要为你用到每个接口返回一个非NULL值. // 接口名称字符串的定义在接口的头文件中. // 浏览器调用这个函数得到你的模块实现的接口的指针. PP_EXPORT const void* PPP_GetInterface(const char* interface_name) { // 为每个PPP接口创建结构体. // 把接口函数放入数据结构中. if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) { static PPP_Instance instance_interface = { &Instance_DidCreate, // 这些函数的定义就不展示了 &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 = { // 这个函数的定义就不展示了. &Instance_HandleInput, }; return &input_interface; } // 没有实现的接口返回NULL. return NULL; } // 定义PPP_InitializeModule, 模块的入口点. // 取得将要使用的浏览器端(PPB)接口的API. 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; }