当前位置:   article > 正文

python引入jit_从llvmjit调用Python代码

llvm capi

正如Eli所说,没有什么能阻止您调用pythoncapi。当您从llvmjit内部调用一个外部函数时,它只会有效地在进程空间上使用dlopen(),因此,如果您在llvmpy内部运行,您已经可以访问所有的Python解释器符号,您甚至可以与调用ExecutionEngine的活动解释器交互,或者可以运行一个新的Python解释器如果需要的话。在

要开始,请使用我们的计算器创建一个新的C文件。在#include

void python_eval(const char* s)

{

PyCodeObject* code = (PyCodeObject*) Py_CompileString(s, "example", Py_file_input);

PyObject* main_module = PyImport_AddModule("__main__");

PyObject* global_dict = PyModule_GetDict(main_module);

PyObject* local_dict = PyDict_New();

PyObject* obj = PyEval_EvalCode(code, global_dict, local_dict);

PyObject* result = PyObject_Str(obj);

// Print the result if you want.

// PyObject_Print(result, stdout, 0);

}

下面是一个小Makefile来编译它:

^{pr2}$

然后我们从LLVM的常见样板开始,但是使用ctypes将cbits.so共享库的共享对象加载到全局进程空间中,这样我们就有了python_eval符号。然后创建一个带有函数的简单LLVM模块,分配一个带有ctypes的Python源的字符串,并将指针从我们的模块传递到运行JIT函数的ExecutionEngine,后者又将Python源代码传递给调用Python C-API的C-function,然后返回LLVM JIT。在import llvm.core as lc

import llvm.ee as le

import ctypes

import inspect

ctypes._dlopen('./cbits.so', ctypes.RTLD_GLOBAL)

pointer = lc.Type.pointer

i32 = lc.Type.int(32)

i64 = lc.Type.int(64)

char_type = lc.Type.int(8)

string_type = pointer(char_type)

zero = lc.Constant.int(i64, 0)

def build():

mod = lc.Module.new('call python')

evalfn = lc.Function.new(mod,

lc.Type.function(lc.Type.void(),

[string_type], False), "python_eval")

funty = lc.Type.function(lc.Type.void(), [string_type])

fn = lc.Function.new(mod, funty, "call")

fn_arg0 = fn.args[0]

fn_arg0.name = "input"

block = fn.append_basic_block("entry")

builder = lc.Builder.new(block)

builder.call(evalfn, [fn_arg0])

builder.ret_void()

return fn, mod

def run(fn, mod, buf):

tm = le.TargetMachine.new(features='', cm=le.CM_JITDEFAULT)

eb = le.EngineBuilder.new(mod)

engine = eb.create(tm)

ptr = ctypes.cast(buf, ctypes.c_voidp)

ax = le.GenericValue.pointer(ptr.value)

print 'IR'.center(80, '=')

print mod

mod.verify()

print 'Assembly'.center(80, '=')

print mod.to_native_assembly()

print 'Result'.center(80, '=')

engine.run_function(fn, [ax])

if __name__ == '__main__':

# If you want to evaluate the source of an existing function

# source_str = inspect.getsource(mypyfn)

# If you want to pass a source string

source_str = "print 'Hello from Python C-API inside of LLVM!'"

buf = ctypes.create_string_buffer(source_str)

fn, mod = build()

run(fn, mod, buf)

您应该得到以下输出:=======================================IR=======================================

; ModuleID = 'call python'

declare void @python_eval(i8*)

define void @call(i8* %input) {

entry:

call void @python_eval(i8* %input)

ret void

}

=====================================Result=====================================

Hello from Python C-API inside of LLVM!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/199174?site
推荐阅读
相关标签
  

闽ICP备14008679号