-
python3调用微软js引擎ChakraCore
有关ChakraCore介绍请移步:https://github.com/Microsoft/ChakraCore
使用案例GitHub源码:https://github.com/pyAppman/ChakraCore
本文主要讲下python调用ChakraCore.dll
参考文献有:https://xz.aliyun.com/t/2450 以及 https://bbs.125.la/forum.php?mod=viewthread&tid=14495171&highlight=ChakraCore
python是解释性语言,网上能搜到的基本都是C、C#、C++、易语言的ChakraCore使用,并没有python使用方法,参考了上面大佬们的相关介绍使用以及官方文档,写了如下可以成功调用的python例子。之所以写这个是因为:第一,暂目前python用于执行js的工具有node,pyv8,js2py,windows系统下的com组件,node性能不好,v8不够全安装费劲不说,对python2更友好,js2py运行小js还可以,大了就不行了,com不够全面比不上node内置的js函数,也不能跨平台,ChakraCore综合了node的全面跟v8的性能,还能跨平台。第二、网上也有不少关于ChakraCore的文章,但是没有python的,而易语言,C,C++这些并不是解释性语言,很多方面跟python不一样。第三、自己能力有限,过程中爬了很多坑,好似盲人过河,也算是想给其他有兴趣的人一点帮助
一、准备工具
python解释器,本人用的32位python3.6.x,其他版本也可以,但是务必用32位,跟dll有关原因不多做说明。
封装的 ChakraCore.dll文件,源文件网上有,可以自行搜索下载,也可以https://github.com/pyAppman/ChakraCore上下载。
二、ChakraCore的部分方法(按顺序执行)
1、JsCreateRuntime(文档:https://github.com/microsoft/ChakraCore/wiki/JsCreateRuntime)
// 创建完整的JavaScript执行环境
2、JsCreateContext(文档:https://github.com/microsoft/ChakraCore/wiki/JsCreateContext)
// 创建一个执行js的上下文环境
3、JsSetCurrentContext(文档:https://github.com/microsoft/ChakraCore/wiki/JsSetCurrentContext)
// 表示一个拥有和别的execution contexts不同的JavaScript全局对象JavaScript的执行环境。
4、JsRunScript(文档:https://github.com/microsoft/ChakraCore/wiki/JsRunScript)
// 执行js
5、JsGetValueType(文档:https://github.com/microsoft/ChakraCore/wiki/JsGetValueType)
// 获取返回值类型(整型,字符串型,列表,字典等)
6、JsConvertValueToString(文档:https://github.com/microsoft/ChakraCore/wiki/JsConvertValueToString)
// 使用标准JavaScript语义将值转换为字符串。
7、JsStringToPointer(文档:https://github.com/microsoft/ChakraCore/wiki/JsStringToPointer)
// 检索字符串值的字符串指针。
8、JsDisposeRuntime(文档:https://github.com/microsoft/ChakraCore/wiki/JsDisposeRuntime)
// 处理runtime,类似于释放
三、附上实战代码:
1、加载dll,初始化数据
1
2
3
4
5
6
7
8
9
10
11
12
|
def __init__( self ): self .source = '' self .dll = windll.LoadLibrary( 'ChakraCore.dll' ) self .init_source = '''(function(){%s;return %s})()''' self .count = 0 self .result = c_wchar_p('') self ._runtime = c_long( 0 ) self ._context = c_long( 0 ) self ._result = c_long( 0 ) self ._type = c_long( 0 ) self ._res_ptr = c_long( 0 ) self ._length_ptr = c_long( 0 ) |
2、创建所需环境
1
2
3
4
5
6
7
8
|
def create_runtime( self ): return self .dll.JsCreateRuntime( 0 , None , pointer( self ._runtime)) def create_context( self ): return self .dll.JsCreateContext( self ._runtime, pointer( self ._context)) def set_current_context( self ): return self .dll.JsSetCurrentContext( self ._context) |
3、组合js代码
1
2
|
def compile ( self , source): self .source = source |
4、执行js并获取结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
def run( self , func, * args): if not self ._runtime: self .create_runtime() self .create_context() self .set_current_context() target = '{name}{arg}' . format (name = func, arg = args) js = self .init_source % ( self .source, target) self .count + = 1 _run = self .dll.JsRunScript(c_wchar_p(js), self .count, c_wchar_p(''), pointer( self ._result)) if _run: self .dispose() return 'JsRunScript Error!' , False return_type = self .dll.JsGetValueType( self ._result, pointer( self ._type)) if return_type: self .dispose() return 'Js Return Type Error!' , False if self ._type.value = = JsValueType_JsArray: self .dispose() return 'List wait' , False if self .dll.JsConvertValueToString( self ._result, pointer( self .result)): self .dispose() return 'JsConvertValueToString Error' , False str_ptr = c_wchar_p('') u_ptr = c_int( 0 ) res = self .dll.JsStringToPointer( self .result, pointer(str_ptr), pointer(u_ptr)) if res: self .dispose() return 'JsStringToPointer Error' , False else : # print(str_ptr.value) # self.dispose() return str_ptr.value, True |
5、释放runtime
1
2
3
4
5
6
7
8
9
10
|
def dispose( self ): # self.dll.JsSetCurrentContext(0) self .result = c_wchar_p('') self .count = 0 self .dll.JsDisposeRuntime( self ._runtime) def __exit__( self , exc_type, exc_val, exc_tb): self .result = c_wchar_p('') self .count = 0 self .dll.JsDisposeRuntime( self ._runtime) |
四、所有源码如下:
1 from ctypes import * 2 3 JsValueType_JsUndefined = 0 # 公开,该值是未定义的值。 4 JsValueType_JsNull = 1 # 公开,值为空值。 5 JsValueType_JsNumber = 2 # 公开,该值是JavaScript数值。 6 JsValueType_JsString = 3 # 公开,该值是JavaScript字符串值。 7 JsValueType_JsBoolean = 4 # 公开,该值是JavaScript布尔值。 8 JsValueType_JsObject = 5 # 公开,该值是JavaScript对象值。 9 JsValueType_JsFunction = 6 # 公开,该值是JavaScript函数对象值。 10 JsValueType_JsError = 7 # 公开,该值是JavaScript错误对象值。 11 JsValueType_JsArray = 8 # 公开,该值是JavaScript数组对象值。 12 JsValueType_JsSymbol = 9 # 公开,该值是JavaScript符号值。 13 JsValueType_JsArrayBuffer = 10 # 公开,该值是JavaScriptArrayBuffer对象值。 14 JsValueType_JsTypedArray = 11 # 公开,该值是JavaScript类型的数组对象值。 15 JsValueType_JsDataView = 12 # 公开,该值是JavaScriptDataView对象值。 16 17 18 class ChakraCore: 19 20 def __init__(self): 21 self.source = '' 22 self.dll = windll.LoadLibrary('ChakraCore.dll') 23 self.init_source = '''(function(){%s;return %s})()''' 24 self.count = 0 25 self.result = c_wchar_p('') 26 self._runtime = c_long(0) 27 self._context = c_long(0) 28 self._result = c_long(0) 29 self._type = c_long(0) 30 self._res_ptr = c_long(0) 31 self._length_ptr = c_long(0) 32 33 def compile(self, source): 34 self.source = source 35 36 def create_runtime(self): 37 return self.dll.JsCreateRuntime(0, None, pointer(self._runtime)) 38 39 def create_context(self): 40 return self.dll.JsCreateContext(self._runtime, pointer(self._context)) 41 42 def set_current_context(self): 43 return self.dll.JsSetCurrentContext(self._context) 44 45 def value(self, value): 46 if value == JsValueType_JsNumber: 47 self.result = c_float(0) 48 elif value == JsValueType_JsString: 49 self.result = c_wchar_p('') 50 if self.dll.JsConvertValueToString(self._result, pointer(self.result)): 51 return 'JsConvertValueToString Error' 52 str_ptr = c_wchar_p('') 53 u_ptr = c_int(0) 54 res = self.dll.JsStringToPointer(self.result, pointer(str_ptr), pointer(u_ptr)) 55 if res: 56 return 'JsStringToPointer Error' 57 else: 58 return str_ptr.value 59 elif value == JsValueType_JsArray: 60 self.result = (c_wchar * 10)() 61 elif value == JsValueType_JsObject: 62 self.result = {} 63 else: 64 self.result = None 65 66 def run(self, func, *args): 67 if not self._runtime: 68 self.create_runtime() 69 self.create_context() 70 self.set_current_context() 71 72 target = '{name}{arg}'.format(name=func, arg=args) 73 js = self.init_source % (self.source, target) 74 self.count += 1 75 _run = self.dll.JsRunScript(c_wchar_p(js), self.count, c_wchar_p(''), pointer(self._result)) 76 if _run: 77 self.dispose() 78 return 'JsRunScript Error!', False 79 return_type = self.dll.JsGetValueType(self._result, pointer(self._type)) 80 if return_type: 81 self.dispose() 82 return 'Js Return Type Error!', False 83 if self._type.value == JsValueType_JsArray: 84 self.dispose() 85 return 'List wait', False 86 if self.dll.JsConvertValueToString(self._result, pointer(self.result)): 87 self.dispose() 88 return 'JsConvertValueToString Error', False 89 str_ptr = c_wchar_p('') 90 u_ptr = c_int(0) 91 res = self.dll.JsStringToPointer(self.result, pointer(str_ptr), pointer(u_ptr)) 92 if res: 93 self.dispose() 94 return 'JsStringToPointer Error', False 95 else: 96 # print(str_ptr.value) 97 # self.dispose() 98 return str_ptr.value, True 99 100 def dispose(self): 101 # self.dll.JsSetCurrentContext(0) 102 self.result = c_wchar_p('') 103 self.count = 0 104 self.dll.JsDisposeRuntime(self._runtime) 105 106 def __exit__(self, exc_type, exc_val, exc_tb): 107 self.result = c_wchar_p('') 108 self.count = 0 109 self.dll.JsDisposeRuntime(self._runtime)
五、参考文献
使用案例GitHub源码:https://github.com/pyAppman/ChakraCore
本文主要讲下python调用ChakraCore.dll
参考文献有:https://xz.aliyun.com/t/2450 以及 https://bbs.125.la/forum.php?mod=viewthread&tid=14495171&highlight=ChakraCore
欢迎大家补充,没有太多的python文档借鉴,是自己一步一个脚印,爬坑爬出来的,好似盲人摸象。写的不好,还请轻喷。