Python ctypesでSpiderMonkeyを呼び出す
PythonでのFFI - ラシウラ の続きで、ctypesの練習にSpiderMonkeyのDLLを呼び出してみました。
べた書きで、後半の例題に必要最低限の情報を使うだけにとどめてます。
参考文献は
および、SpiderMonkeyのヘッダファイルです。
import ctypes # ctypes: http://python.net/crew/theller/ctypes/tutorial.html # spidermonkey: http://www.mozilla.org/js/spidermonkey/tutorial.html # setup libjs = ctypes.CDLL("libmozjs.so") # from ubuntu libmozjs package class JSClass(ctypes.Structure): _fields_ = [ ("name", ctypes.c_char_p), ("flags", ctypes.c_uint32), ("addProperty", libjs._FuncPtr), ("delProperty", libjs._FuncPtr), ("getProperty", libjs._FuncPtr), ("setProperty", libjs._FuncPtr), ("enumrate", libjs._FuncPtr), ("resolve", libjs._FuncPtr), ("convert", libjs._FuncPtr), ("finalize", libjs._FuncPtr), ("getObjectOps", libjs._FuncPtr), ("checkAccess", libjs._FuncPtr), ("call", libjs._FuncPtr), ("construct", libjs._FuncPtr), ("xdrObject", libjs._FuncPtr), ("hasInstance", libjs._FuncPtr), ("mark", libjs._FuncPtr), ("reserveSlots", libjs._FuncPtr), ] pass global_class = JSClass() global_class.name = "global" global_class.flags = 0 global_class.addProperty = libjs.JS_PropertyStub global_class.delProperty = libjs.JS_PropertyStub global_class.getProperty = libjs.JS_PropertyStub global_class.setProperty = libjs.JS_PropertyStub global_class.enumerate = libjs.JS_EnumerateStub global_class.resolve = libjs.JS_ResolveStub global_class.convert = libjs.JS_ConvertStub global_class.finalize = libjs.JS_FinalizeStub rt = libjs.JS_Init(0x100000) cx = libjs.JS_NewContext(rt, 0x1000) globe = libjs.JS_NewObject(cx, ctypes.pointer(global_class), None, None) libjs.JS_InitStandardClasses(cx, globe) libjs.JS_GetStringBytes.restype = ctypes.c_char_p # see macros in jsapi.h: STRING_TO_JSVAL def String2jsval(jsstr): return jsstr | 0x4 # example: evaluate script = """ var a = 100; a + "abc"; """ ret = ctypes.c_long(0) filename = "snip" lineno = 0 libjs.JS_EvaluateScript(cx, globe, script, len(script), filename, lineno, ctypes.pointer(ret)) strp = libjs.JS_ValueToString(cx, ret) print libjs.JS_GetStringBytes(strp) # example: function and call it script = """ function (name) { return "Hello " + name; } """ ret = ctypes.c_long(0) filename = "snip" lineno = 0 libjs.JS_EvaluateScript(cx, globe, script, len(script), filename, lineno, ctypes.pointer(ret)) funp = libjs.JS_ValueToFunction(cx, ret) name = "Taro" jsstr = libjs.JS_NewStringCopyN(cx, name, len(name)) argvt = ctypes.c_long * 1 argv = argvt(String2jsval(jsstr)) libjs.JS_CallFunction(cx, None, funp, len(argv), ctypes.pointer(argv), ctypes.pointer(ret)) strp = libjs.JS_ValueToString(cx, ret) print libjs.JS_GetStringBytes(strp)
(注意点はContext cxはスレッドごとに作る必要があること。)
すでにPython SpiderMonkeyがあるんですけどね。