SpiderMonkey-让你的C++程序支持JavaScript脚本
译序
有些网友对为什么D2JSP能执行JavaScript脚本程序感到奇怪,因此我翻译了这篇文章,原文在这里。这篇教程手把手教你怎样利用SpiderMonkey创建一个能执行JavaScript脚本的C++程序,并让JavaScript脚本操纵你的C++程序的内部数据、操作。从这篇教程能够看到在SpiderMonkey引擎的帮助下,让C++程序支持JavaScript脚本是一件非常easy的事,更棒的是SpiderMonkey也能够在Macintosh和Unix平台使用。
SpiderMonkey是Gecko(Firefox浏览器的内核)的JavaScript脚本引擎,具体文档请看这里。
下面为翻译内容。
------------------------------------------------
本教程的目的是教你怎样用JavaScript做为脚本语言使你的C++程序自己主动化。
SpiderMonkey
SpiderMonkey是Mozilla项目的一部分,用C语言写成,是负责运行JavaScript脚本的引擎。另外另一个叫Rhino的Java引擎。
SpiderMonkey的最新版本号可在这里下载。它是以源码形式公布的,因此你必须自己编译它(译注:事实上网上有非常多编译好的二进制版本号,google一下js32.dll就可找到)。Visual C++用户能够在src文件夹下找到Workspace项目project文件来编译,编译结果会产生一个叫'js32.dll'的dll文件。
SpiderMonkey也能够在Macintosh和Unix上使用,想了解怎样在这些平台上进行编译请阅读Readme.html。
在C++中运行JavaScript程序
步骤1-创建JavaScript runtime(执行时实例)
初始化一个JavaScript runtime可用JS_NewRuntime方法,该方法将为runtime分配内存,同一时候还得指定一个字节数,当内存分配超过这个数字时垃圾收集器会自己主动执行。







步骤2-创建context(上下文环境)
Context指明了脚本执行所需的栈大小,即分配给脚本执行栈的私有内存数量。每一个脚本都和它自己的context相关联。
当一个context正在被某个脚本或线程使用时,其它脚本或线程不能使用该context。只是在脚本或线程结束时,该context能够被下一个脚本或线程重用。
创建一个新context可用JS_NewContext方法。context必须关联到一个runtime,调用JS_NewContext方法时还必须指定栈的大小。






步骤3-初始化全局对象
在一个脚本開始执行前,必须初始化一些大多数脚本会用到的通用的JavaScript函数和内置(build-in)类对象。
全局对象是在一个JSClass结构中描写叙述的。该结构能够按下面方式初始化:









如今创建和初始化这个全局对象:JSObject *globalObj = JS_NewObject(cx, &globalClass, 0, 0);
JS_InitStandardClasses(cx, globalObj);
步骤4-运行脚本
运行脚本的一种途径是使用JS_EvaluateScript方法:





在这个脚本中,假设运行正确的话当天数据会保存在rval中。rval包括最后一个运行函数的结果。JS_EvaluteScript返回JS_TRUE代表运行成功,返回JS_FALSE则代表有发生错误。
从rval得到对应的字符串值能够用以下的方法。在这里我不想解释全部细节,想获得更具体的信息请自己查API文档。


步骤5-清理脚本引擎
程序结束前必须对脚本引擎做一些清理工作:JS_DestroyContext(cx);
JS_DestroyRuntime(rt);
在C++中定义一个在JavaScript中用的类
这个样例中用到的类定义例如以下:

















步骤1-JavaScript类
从Customer类派生一个你想在JavaScript中用的新的C++类,或者创建一个包括一个Customer类型成员变量的新类。
给JavaScript用的类得有一个JSClass结构,为此得创建一个JSClass类型的静态成员变量,该变量会被其它类用到,因此还得把它声明为public变量。别的类能够用该结构来推断对象的类型(见JS_InstanceOf API)。




































该JSClass结构里包括了JavaScript类的名字、标志位以及给脚本引擎用的回调函数的名字。举个样例,脚本引擎使用回调函数从类中获取某个属性值。
在C++类的实现文件里定义JSClass结构例如以下:










用到的回调函数是JSCustomer::JSGetProperty,JSCustomer::JSSetProperty和JSCustomer::JSDestructor。脚本引擎调用JSGetProperty获取属性值,调用JSSetProperty设置属性值,调用JSDestructor析构JavaScript对象。
JSCLASS_HAS_PRIVATE标志位会让脚本引擎分配一些内存,这样你能够在JavaScript对象中附加一些自己定义数据,比方能够用它来保存类指针。
回调函数以C++的类静态成员函数方式存在:





步骤2-初始化你的JavaScript对象
创建另外一个叫JSInit的静态方法,见以下的样例,该方法将在应用程序创建JavaScript runtime时被调用。

JSInit方法的实现大约例如以下:









对象在脚本中被具象化(译注:instantiated,简而言之就是对象new出来的时候)的时候,静态方法JSConstructor会被调用。在这种方法中能够用JS_SetPrivate API给该对象附加一些自己定义数据。












JSConstructor构造方法能够带多个參数,用来初始化类。眼下为止已经在堆上创建了一个指针,还须要一种途径来销毁它,这能够通过JS_Destructor完毕:







步骤3-加入属性
加入一个JSPropertySpec类型的静态成员数组来存放属性信息,同一时候定义属性ID的枚举变量。







在实现文件里例如以下初始化该数组:










数组的最后一个元素必须为空,当中每一个元素是一个带有3个元素的数组。第一个元素是给JavaScript用的名字。第二个元素是该属性的唯一ID,将传递给回调函数。第三个元素是标志位,JSPROP_ENUMERATE代表脚本在枚举Customer对象的全部属性时能够看到该属性,也能够指定JSPROP_READONLY来表明该属性不同意被脚本程序改变。
如今能够实现该属性的getting和setting回调函数了:









































建议在属性的回调函数中返回JS_TRUE。假设返回JS_FALSE,则当该属性在对象中没找到时(脚本引擎)不会进行搜索。
步骤4-加入方法
创建一个JSFunctionSpec类型的静态成员数组:

在实现文件里例如以下初始化该数组:








最后一个元素必须为空,当中每一个元素是一个带有5个元素的数组。第一个元素是给脚本程序用的方法名称。第二个是一个全局或者静态成员函数的名称。第三个是该方法的參数个数。最后两个能够忽略。
在类中创建一个静态方法:


该函数成功时返回JS_TRUE,否则返回JS_FALSE。注意真正的JavaScript方法的返回值保存在rval參数中。
该方法的一个实现样例:











使用样例
以下的脚本使用了前面创建的对象:




别忘了在创建context时初始化JavaScript对象:

类常量
JavaScript类型
这一章解释在JavaScript中会用到的几种类型:Integer,String,Boolean,Double,Object和Function。
构建中。。。。。。
垃圾回收
构建中。。。。。。
下载
main.cpp演示怎样运行一个javascript程序。JSCustomer.h演示Customer的JavaScript类的定义。JSCustomer.cpp演示JSCustomer的实现。Customer.h是Customer C++类的定义。example.js示例脚本程序。
SpiderMonkey-让你的C++程序支持JavaScript脚本的更多相关文章
- 测试浏览器是否支持JavaScript脚本
如果用户不能确定浏览器是否支持JavaScript脚本,那么可以应用HTML提供的注释符号进行验证.HTML注释符号是以 <-- 开始以 --> 结束的.如果在此注释符号内编写 JavaS ...
- java ScriptEngine 使用 (支持JavaScript脚本,eval()函数等)
Java SE 6最引人注目的新功能之一就是内嵌了脚本支持.在默认情况下,Java SE 6只支持JavaScript,但这并不以为着Java SE 6只能支持JavaScript.在Java SE ...
- Java 支持JavaScript脚本计算
Java支持了JavaScript脚本的执行计算能力: import javax.script.Invocable; import javax.script.ScriptEngine; import ...
- IE浏览器开启对JavaScript脚本的支持
在IE浏览器的"工具"菜单中选择"internet选项",在弹出命令对话框中选择"安全"选项卡.在该选项卡下的"该区域的安全级别& ...
- TMS WEB Core v1.2预览版:新的Electron应用程序支持
2019年2月20日,星期三 几个月前,我们已经开始与Electron进行实验.在工作概念验证之后,我们的目标是为Delphi开发人员尽可能多地包装Electron API.但当然不仅仅是可以使用的E ...
- 微信小程序开发:学习笔记[5]——JavaScript脚本
微信小程序开发:学习笔记[5]——JavaScript脚本 快速开始 介绍 小程序的主要开发语言是 JavaScript ,开发者使用 JavaScript 来开发业务逻辑以及调用小程序的 API 来 ...
- [Swift通天遁地]一、超级工具-(6)通过JavaScript(脚本)代码调用设备的源生程序
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 如果您的浏览器不支持javascript功能
如果您的浏览器不支持javascript功能或被禁止使用,那么在访问许多网站(包括此网站)时,某些功能将不可用.我们建议您打开javascript功能以获得最佳的浏览效果.以下是打开它的可能原因和方法 ...
- 你的程序支持复杂的时间调度嘛?如约而来的 java 版本
你的程序支持复杂的时间调度嘛? 这篇文章介绍了时间适配器的c#版本,是给客户端用的,服务器自然也要有一套对应的做法,java版本的 [年][月][日][星期][时间] [*][*][*][*][*] ...
随机推荐
- Apache HTTP Server多个拒绝服务漏洞
漏洞版本: Apache Group Apache HTTP Server < 2.4.9 漏洞描述: BUGTRAQ ID: 66303 CVE ID: CVE-2013-6438,CVE-2 ...
- BZOJ3792: 跑步
题解: 感觉被坑出翔... 显然我们把矩阵乘法中的点当成原图中的边就可以了. 先写opertor 在struct里面居然只能带一个变量?... 放到外面,然后还得加引用? 然后题目描述不清,重边怎么算 ...
- JDK7新特性之fork/join框架
The fork/join framework is an implementation of the ExecutorService interface that helps you take ad ...
- Java [Leetcode 40]Combination Sum II
题目描述: Given a collection of candidate numbers (C) and a target number (T), find all unique combinati ...
- 选择select框跳出信息
<html > <body > <select type="select" name=s1 onChange=alert("你选择了&quo ...
- 关于Memcache mutex设计模式的.net实现
之前在网上看过memcache-mutex的场景分析和实现代码,这里将.net方式加以实现,当然这里主要是依据原文的伪代码照猫画虎,以此做为总结及记录.如果您对相应实现感兴趣可以尝试使用本文提供的代码 ...
- windows和linux间互传文件
方法1:Xshell传输文件 用rz,sz命令在xshell传输文件 很好用,然后有时候想在windows和linux上传或下载某个文件,其实有个很简单的方法就是rz,sz 首先你的Ubuntu需要安 ...
- 位操作:BitVector32结构 z
目录 温习位操作 BitVector32的位操作 CreateMask方法 使用BitVector32.Section来存储小整数 BitVector32结构体位于System.Collections ...
- 黑盒测试用例设计方法&理论结合实际 -> 边界值分析法
一. 概念 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法.通常边界值分析法是作为对等价类划分法的补充,这种情况下,其测试用例来自等价类的边界. 二. 边界值分析法的应用 根据大量的测 ...
- JqueryTips小实验,浏览器滚动条不限制
最近做公司的项目有些地方可能需要一些小提示,于是自己建立项目研究tips.在此之前看到过一些别人写的JqueryTips,于是借鉴了一些别人的经验在此基础上我做出了一些改进. 有的同学可能使用过其他一 ...