原文链接:https://developer.chrome.com/native-client/devguide/coding/application-structure
注意:已针对ChromeOS以外的平台公布了此处所述技术的弃用。
请访问我们的 迁移指南 了解详情。
应用结构
“开发人员指南”的这一部分描述了Native Client应用程序的一般结构。本节假定您熟悉技术概述中提供的材料。
这里使用“Hello,World”示例来说明基本的Native Client编程技术。您可以在Native Client SDK下载的/ getting_started / part1目录中找到此代码 。
应用组件
Native Client应用程序通常包含以下组件:
- 一个HTML文件;
- JavaScript代码,可以包含在HTML文件中,也可以包含在一个或多个单独的.js文件中;
- CSS样式,可以包含在HTML文件中,也可以包含在一个或多个单独的.css文件中;
- Native Client清单文件(扩展名为.nmf),指定如何为不同的处理器加载Native Client模块; 和
- Native Client模块,用C或C ++编写,并编译成可移植的可执行文件(扩展名为.pexe)或(如果使用Chrome Web Store),特定于体系结构的可执行文件(扩展名为.nexe)。
在Chrome网上应用店中发布的应用程序 还包括Chrome网上应用店清单文件(manifest.json)
和一个或多个图标文件。
HTML文件和<embed>元素
<embed>
HTML文件中的元素触发加载Native Client模块,并在网页上指定由模块管理的矩形。这是“Hello,World”应用程序中的<embed>元素:
<embed id="hello_tutorial"
width=0 height=0
src="hello_tutorial.nmf"
type="application/x-pnacl" />
在<embed>
元素中:
名称
是Native Client模块的DOM名称属性(“nacl_module”通常用作约定)
ID
指定Native Client模块的DOM ID
宽度,高度
指定由Native Client模块管理的网页上矩形的大小(如果模块没有可见区域,则这些值可以为0)
SRC
指的是Native Client清单文件,用于根据用户计算机的体系结构确定要加载的模块版本(有关详细信息,请参阅下一节)
类型
指定嵌入内容的MIME类型; 对于Portable Native Client模块,类型必须是“application / x-pnacl”。对于特定于体系结构的Native Client模块,类型必须为“application / x-nacl”
清单文件
Native Client应用程序有两种类型的清单文件:Chrome Web Store清单文件和Native Client清单文件。
一个Chrome网上应用店清单文件与有关发表在Chrome网上应用店的网络应用程序信息的文件。名为的文件manifest.json
是Chrome网上应用店中发布的应用程序所必需的。有关此文件的详细信息,请参阅分发您的应用程序。以及Chrome网上应用店清单文件格式。
阿本机客户端清单文件是指定本机客户端模块(可执行程序)要加载的一个文件。对于PNaCl,它指定一个可移植的可执行文件; 否则,它为每个受支持的最终用户计算机体系结构指定一个(例如x86-32,x86-64或ARM)。所有Native Client应用程序都需要此文件。该文件的扩展名为.nmf。
使用PNaCl的应用程序的清单文件很简单。以下是hello world示例的清单:
{
"program": {
"portable": {
"pnacl-translate": {
"url": "hello_tutorial.pexe"
}
}
}
}
对于不使用PNaCl的Chrome Web Store应用程序,典型的清单文件包含具有单个顶级键/值对的JSON字典:“程序”键和由嵌套字典组成的值。嵌套字典包含与支持的计算机体系结构的名称相对应的键,以及引用要为给定体系结构加载的文件的值 - 特别是由"url"
密钥给出的.nexe文件的URL 。URL是相对于清单文件的位置指定的。这是一个例子:
{
"program": {
"x86-32": {
"url": "hello_tutorial_x86_32.nexe"
},
"x86-64": {
"url": "hello_tutorial_x86_64.nexe"
},
"arm": {
"url": "hello_tutorial_arm.nexe"
}
}
}
对于使用glibc 库的应用程序,清单文件还必须包含“files”键,用于指定应用程序使用的共享库。这在动态链接和加载glibc中有详细讨论 。要查看一些示例清单文件,请在SDK中构建一些示例应用程序(make
在示例子目录中运行)并查看生成的清单文件。
在大多数情况下,您可以简单地使用随SDK提供的Python脚本 create_nmf.py
,在编译步骤中为您的应用程序创建清单文件(有关如何操作的说明,请参阅任何SDK示例中的Makefile) 。清单文件格式也有 记录。
模块和实例
Native Client 模块是编译为PNaCl .pexe文件或NaCl .nexe文件的C或C ++代码。
一个实例是一个网页,是由模块管理上的一个矩形。实例可以具有width = 0和height = 0的维度,这意味着该实例在网页上没有任何可见组件。通过<embed>
在网页中包含元素来创建实例。该<embed>
元素引用Native Client清单文件,该文件加载模块的适当版本(可移植或特定于最终用户的体系结构)。通过使用<embed>
涉及模块的多个元素,模块可以多次包括在网页中 ; 在这种情况下,Native Client运行时系统会加载模块一次,并创建由模块管理的多个实例。
Native Client模块:仔细看看
Native Client模块必须包含三个组件:
- 一个叫做的工厂功能
CreateModule()
- Module类(派生自
pp::Module
类) - Instance类(派生自
pp:Instance
类)
在“Hello tutorial”示例中(在getting_started/part1
NaCl SDK 的目录中),这三个组件在文件中指定hello_tutorial.cc
。这是工厂功能:
Module* CreateModule() {
return new HelloTutorialModule();
}
Native Client模块没有main()
功能。该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消息传递系统。
仅调用NaCl代码来处理各种浏览器发出的事件和回调。无需通过调用该exit()
函数来关闭NaCl实例。当用户离开网页时,NaCl模块将被关闭,否则NaCl模块将<embed>
被破坏。如果NaCl模块确实调用了该exit()
函数,则该实例将发出一个可以在Javascript中处理的crash
事件 。
虽然Native Client应用程序需要CreateModule()
工厂函数,Module
类和 Instance
类,但上面显示的代码示例实际上并不执行任何操作。Developer's Guide中的后续部分以这些代码示例为基础,并添加了更多有趣的功能。
CC-By 3.0许可下提供的内容