如何在spidermonkey嵌入中提供js-cypes
How to provide js-ctypes in a spidermonkey embedding?
摘要
我已经看过SpiderMonkey‘shell’应用程序用于创建ctypes JavaScript对象的代码,但我还不是一个新手C程序员。由于现代构建系统所发出的疯狂程度各不相同,我似乎无法找到将程序与所需功能真正链接起来的代码或命令。
方法。疯狂
这个由Mozilla Devs实现的js-cytpes是一个很棒的补充。自其诞生以来,脚本主要用于控制更严格、更健壮的应用程序。js-ctypes在SpiderMonkey项目中的出现,使JavaScript能够脱颖而出,成为一种成熟的面向对象的快速应用程序开发语言,远远超过了微软的VB6等各种古老的应用程序开发软件所设定的标准。
我们开始吧
我用这个配置构建了SpiderMonkey/使用系统nspr 配置-启用ctypes
随后成功执行:make&;制作安装
js shell运行良好,并且验证了全局ctypes javascript对象在该shell中的可操作性。
使用从How to embed the JavaScript Engine-MDN的第一个源代码列表中提取的代码,我试图通过在第66行插入以下代码来实例化JavaScript ctypes对象:
/* Populate the global object with the ctypes object. */
if (!JS_InitCTypesClass(cx, global))
return NULL;
/*
我用:g++$(./js-config--cflags-libs)hello.cpp-o hello 编译
它编译时有几个警告:
hello.cpp: In function ‘int main(int, const char**)’:
hello.cpp:69:16: warning: converting to non-pointer type ‘int’ from NULL [-Wconversion-null]
hello.cpp:80:20: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
hello.cpp:89:17: warning: NULL used in arithmetic [-Wpointer-arith]
但是当你运行应用程序时:
./hello: symbol lookup error: ./hello: undefined symbol: JS_InitCTypesClass
此外
JS_InitCTypesClass在"dist/include/jsapi.h"中声明为extern,但该函数驻留在"ctypes/ctypes.cpp"中,该函数包含自己的头"ctypes.h",并在"make"到yeild"期间的某个时间点由某个命令编译/正如我之前所说的,我还不是一个C代码的新手,我真的不知道在这里该做什么。
请给出一个使js-cytpes对象在嵌入中起作用的一般示例或给出指导。
黑客
我已经意识到,由于头文件中的条件定义以及零散的lib和头位置,链接失败了。好吧。。。我试图在命令行上定义JS_HAS_CTYPES,但如果它能起作用,那肯定是不够的。
我决定,由于SpiderMonkey shell有自己独特的makefile,并且已经可以访问我试图捕获的功能,只需将js.cpp重命名为js.cpp.tmp,并允许我的代码放在它的位置,几乎就成功了。
该文件编译良好,在应用程序执行时没有引发运行时链接错误,但代码("JSNativeObject"ctypes)几乎完全使JS_InitCTypesClass失败。看到我的链接错误早已被遗忘,我立即查看了make的输出,看看我是否可以"刷"编译代码。。。我们有宾果!
编译
在将shell/js.cpp恢复到其原始目标后,我将hello.cpp移动到spidermonkey的根源目录,并开始更正makefile创建的相对路径,同时删除那些显然不存在或与我的应用程序无关的构造。
虽然以下命令似乎呈现了一个可操作的二进制文件,但作者无法对该列表的正确性或完整性给出任何关联。
c++ -o hello.o -c -Idist/system_wrappers_js -include config/gcc_hidden.h
-DEXPORT_JS_API -DOSTYPE="Linux3.2" -DOSARCH=Linux -I. -Idist/include
-Idist/include/nsprpub -I/usr/include/nspr -fPIC -fno-rtti
-fno-exceptions -Wall -Wpointer-arith -Woverloaded-virtual -Wsynth
-Wno-ctor-dtor-privacy -Wno-non-virtual-dtor -Wcast-align
-Wno-invalid-offsetof -Wno-variadic-macros -Werror=return-type -pedantic
-Wno-long-long -fno-strict-aliasing -pthread -pipe -DNDEBUG -DTRIMMED -Os
-freorder-blocks -fomit-frame-pointer -DJS_HAS_CTYPES -DMOZILLA_CLIENT
-include js-confdefs.h -MD -MF .deps/hello.pp hello.cpp;
c++ -o hello -fno-rtti -fno-exceptions -Wall -Wpointer-arith
-Woverloaded-virtual -Wsynth -Wno-ctor-dtor-privacy
-Wno-non-virtual-dtor -Wcast-align -Wno-invalid-offsetof
-Wno-variadic-macros -Werror=return-type -pedantic
-Wno-long-long -fno-strict-aliasing -pthread -pipe -DNDEBUG
-DTRIMMED -Os -freorder-blocks -fomit-frame-pointer hello.o
-lpthread -Wl,-rpath-link,/bin -Wl,-rpath-link,/usr/local/lib
-Ldist/bin -Ldist/lib -L/usr/lib -lplds4 -lplc4 -lnspr4
-lpthread -ldl editline/libeditline.a libjs_static.a -ldl;
上面列出的两个命令被放入一个名为"mkhello"的可执行shell脚本中,该脚本被保存到根源目录中
据我所知,这是一种分两个阶段的汇编方法。我不确定是什么原因,但这个解释似乎很有教育意义。想法?
编辑有关"两阶段编译方法"的解释,请参阅下面的注释。
代码:hello.cpp
/*
* This define is for Windows only, it is a work-around for bug 661663.
*/
#ifdef _MSC_VER
# define XP_WIN
#endif
/* Include the JSAPI header file to get access to SpiderMonkey. */
#include "jsapi.h"
/* The class of the global object. */
static JSClass global_class = {
"global", JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
};
/* The error reporter callback. */
void reportError(JSContext *cx, const char *message, JSErrorReport *report)
{
fprintf(stderr, "%s:%u:%sn",
report->filename ? report->filename : "<no filename="filename">",
(unsigned int) report->lineno,
message);
}
int main(int argc, const char *argv[])
{
/* JSAPI variables. */
JSRuntime *rt;
JSContext *cx;
JSObject *global;
/* Create a JS runtime. You always need at least one runtime per process. */
rt = JS_NewRuntime(8 * 1024 * 1024);
if (rt == NULL)
return 1;
/*
* Create a context. You always need a context per thread.
* Note that this program is not multi-threaded.
*/
cx = JS_NewContext(rt, 8192);
if (cx == NULL)
return 1;
JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT);
JS_SetVersion(cx, JSVERSION_LATEST);
JS_SetErrorReporter(cx, reportError);
/*
* Create the global object in a new compartment.
* You always need a global object per context.
*/
global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
if (global == NULL)
return 1;
/*
* Populate the global object with the standard JavaScript
* function and object classes, such as Object, Array, Date.
*/
if (!JS_InitStandardClasses(cx, global))
return 1;
/* Populate the global object with the ctypes object. */
if (!JS_InitCTypesClass(cx, global))
return NULL;
/*
/* Your application code here. This may include JSAPI calls
* to create your own custom JavaScript objects and to run scripts.
*
* The following example code creates a literal JavaScript script,
* evaluates it, and prints the result to stdout.
*
* Errors are conventionally saved in a JSBool variable named ok.
*/
char *script = "ctypes.open";
jsval rval;
JSString *str;
JSBool ok;
const char *filename = "noname";
uintN lineno = 0;
ok = JS_EvaluateScript(cx, global, script, strlen(script),
filename, lineno, &rval);
if (rval == NULL | rval == JS_FALSE)
return 1;
str = JS_ValueToString(cx, rval);
printf("%sn", JS_EncodeString(cx, str));
/* End of your application code */
/* Clean things up and shut down SpiderMonkey. */
JS_DestroyContext(cx);
JS_DestroyRuntime(rt);
JS_ShutDown();
return 0;
}
结论
$ ./mkhello
# ...
# error free garbage scrolls....
$ ./hello
function open() {
[native code]
}
按照这个例子为SpiderMonkey嵌入提供js-cypes。您可能需要也可能不需要按顺序重新创建这些步骤,但从我目前的角度来看,强烈建议您这样做。
问题是:大多数平台发行商对代码开发人员给出的建议一无所知。因此,在大多数(如果不是所有)托管该库的系统上,都没有为mozjs185启用js-cypes。这给您留下了一些问题需要解决。
在您配置了--enable ctypes和--with系统nspr,然后是make
和make install
(可能需要是最后一个命令的根)之后,
您的系统上可能有两个版本的libmozjs185.so。一个启用了ctypes(位于/usr/local/lib),另一个未启用ctypes的(位于/usr/lib)。
根据问题,您希望使用ctypes链接到库。因此,这就是通过在编译器中指定:-L/usr/local/lib -lnspr4 -lmozjs185
来实现的。它可以编译。但当应用程序运行时,os库加载程序将加载它找到的库的第一个实例。不幸的是,这可能是位于/usr/lib中的库,并且此版本可能没有启用ctypes。这就是你会遇到这个[解决]问题的地方:g++使用共享库的未定义符号错误
底线是:同一个库的多个版本造成了一个地狱般的问题。因此,向spidermonkey嵌入提供js-ctypes的最佳方法是在启用了ctypes的静态版本的mozjs185中链接到您的程序,除非您想编写一个用于处理多个平台库加载器的库,或者创建您自己的(mozjs 185的更名版本),我已经在@SpiderMonkeyBuild Documentation-MDN 中详细介绍了这一点
要执行静态链接,您需要将这些参数与g++一起使用:-lnspr4 -lpthread -lmozjs185-1.0
,前提是您已经正确构建并安装了开发包。这是为spidermonkey嵌入提供js-cypes的"最佳"(独立于平台)方式。尽管这确实会使应用程序的大小至少增加3.5 MB。如果您已经构建了调试版本,它可能会大15倍以上。
- JS相等运算符(如===)是否可以使用embind类型
- 在 ubuntu 上安装 node js pulsar 客户端
- 如何在 Arduino 字符串的开头添加元素.类似于 JS unshift();
- Node.js fs.open() 在尝试打开 4 个以上的命名管道 (FIFO) 后挂起
- 如何在 Cheerp/js 中迭代动态命名的对象?
- 如何与 Cheerp/js 中的 extern 变量接口?
- 在 node.js 中将缓冲区从 C++ 转换为 UTF-8 字符串
- glfw 的基本设置会导致与 emscripten 生成的 js 文件中的事件侦听器有关的运行时错误
- 如何在C++中使用带有SFML的http reqest从节点.js服务器获取数据?
- 使用 Node.js N-API 调用 C 函数时,不会显示预期的输出
- 将数据从 OpenCV C++传递到 NodeJS/JS |电子
- C++ - 实现JS的setTimeout的现代方法
- 节点.js HTTP 无法通过套接字接收来自C++客户端的请求
- 如何使用 v8 本机插件将 C++ 数组交付到 Node.js
- 将二进制字符串/文件内容从 c++ 传递到节点 js
- 有没有类似的函数,比如 c++ 中的 JS Array.prototype.map?
- C++ 和 node.js 之间的 RSA 加密
- 从C++回调函数发出节点.js事件
- node.js Nan:在函数C++调用 JavaScript 回调
- 如何在spidermonkey嵌入中提供js-cypes