Category Archives: JavaScript

Embed SpiderMonkey in your code

SpiderMonkeyMozilla下的一个开源项目,是用来解析和运行JavaScript脚本的,分JAVA和C两种实现版本。为了能让自己的程序更加灵活和易扩展,加入脚本支撑是一个非常有效的方式。今天尝试了一下把SpiderMonkey加入到自己的程序中,运行了一个简单的脚本。

下载获得js-1.60.tar.gz的tarball并解压,用vc6打开src下的js.mdp,vc6会提示你转换到新版的dsp,然后设定Active Project为win32 release,build,稍等一会就在release目录下得到js32.dll和js32.lib,把这两个文件以及src下的*.h,复制到你的应用程序目录下(或者直接设定你的Project的搜索路径也行)。

附测试代码:
#include <stdio.h>
#define XP_WIN
#include "jsapi.h"
#pragma comment(lib, "js32.lib")

//---------------------------------------------------------------------------
static JSBool my_abs(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
{
  jsdouble x, z;
  if (!JS_ValueToNumber(cx, argv[0], &x)) return JS_FALSE;
  z = (x<0) ? -x : x;
  return JS_NewDoubleValue(cx, z, rval);
}
static JSFunctionSpec my_functions[] = {
  { "abs", my_abs, 1},{0}
  };

char* VersionToString(JSVersion v)
{
  switch(v) {
  case JSVERSION_1_0: return "JavaScript 1.0";
  case JSVERSION_1_1: return "JavaScript 1.1";
  case JSVERSION_1_2: return "JavaScript 1.2";
  case JSVERSION_1_3: return "JavaScript 1.3";
  case JSVERSION_1_4: return "JavaScript 1.4";
  case JSVERSION_ECMA_3: return "ECMA 262 Edition 3";
  case JSVERSION_1_5: return "JavaScript 1.5";
  case JSVERSION_DEFAULT: return "Default JavaScript Version";
  case JSVERSION_UNKNOWN: return "Unknown JavaScript version";
  default: return "Unknown JavaScript version";
  }
}
int main()
{
  JSVersion version; // 版本号
  JSRuntime *rt; // 运行时的内存空间
  JSContext *cx; // 环境句柄
  JSObject *glob, *it; // 对象(函数,类等)
  JSBool builtins;
  // 全局对象
  JSClass global_class = {
  "global",0,
  JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,
  JS_EnumerateStub,JS_ResolveStub,JS_ConvertStub,JS_FinalizeStub
  };
  rt = JS_NewRuntime(8L * 1024L * 1024L);
  if (!rt) return 1;
  cx = JS_NewContext(rt, 8192);
  if (cx == NULL) return 1;
  version = JS_GetVersion(cx);
  printf("Script Version: %s", VersionToString(version));

glob = JS_NewObject(cx, &global_class, NULL, NULL);
  builtins = JS_InitStandardClasses(cx, glob);

JS_DefineFunctions(cx, glob, my_functions);
  //JS_DefineFunction(cx, glob, "abs", my_abs, DOIT_MINARGS, 0);

  // FILE *fp = fopen("hello.js", "rb");
  // char szScript[512];
  // fread(buff, 1, 510, fp);
  // fclose(fp);
  char* szScript = "var today=Date(); today.toString(); var n=2001; n=n+1; var a=-305; abs(a);";
  jsval rval;
  JSString *str;
  char* pFileName = NULL;
  int nLines = 0;

if (JS_EvaluateScript(cx, glob, szScript, strlen(szScript), pFileName, nLines, &rval) == JS_FALSE) {
  printf("Error Occured while Run Script Engine.\n");
  return 1;
  }
  str = JS_ValueToString(cx, rval); // rval返回脚本最后执行的那个变量的值
  printf("Script Result: %s\n", JS_GetStringBytes(str));

JS_DestroyContext(cx);
  JS_DestroyRuntime(rt);
  JS_ShutDown();
  return 0;
}

//---------------------------------------------------------------------------
注:
如果需要让调试器跟踪进如SpiderMonkey的源代码,需要生成debug版的js32.dll和js32.lib。
参考链接:
How to Embed JS Engine.
JavaScript C Engine Embedder’s Guide.
下载地址:
http://ftp.mozilla.org/pub/mozilla.org/js/