15.12 将函数指针转换为可调用对象

    模块可被用来创建包装任意内存地址的Python可调用对象。下面的例子演示了怎样获取C函数的原始、底层地址,以及如何将其转换为一个可调用对象:

    本节看上去可能有点神秘,偏底层一点。但是,但是它被广泛使用于各种高级代码生成技术比如即时编译,在LLVM函数库中可以看到。

    1. >>> from llvm.core import Module, Function, Type, Builder
    2. >>> mod = Module.new('example')
    3. >>> f = Function.new(mod,Type.function(Type.double(), \
    4. [Type.double(), Type.double()], False), 'foo')
    5. >>> block = f.append_basic_block('entry')
    6. >>> builder = Builder.new(block)
    7. >>> y2 = builder.fmul(f.args[1],f.args[1])
    8. >>> r = builder.fadd(x2,y2)
    9. >>> builder.ret(r)
    10. <llvm.core.Instruction object at 0x10078e990>
    11. >>> from llvm.ee import ExecutionEngine
    12. >>> engine = ExecutionEngine.new(mod)
    13. >>> ptr = engine.get_pointer_to_function(f)
    14. >>> ptr
    15. 4325863440
    16.  
    17. >>> # Call the resulting function
    18. >>> foo(2,3)
    19. 13.0
    20. >>> foo(4,5)
    21. 41.0
    22. >>> foo(1,2)
    23. 5.0
    24. >>>

    并不是说在这个层面犯了任何错误就会导致Python解释器挂掉。要记得的是你是在直接跟机器级别的内存地址和本地机器码打交道,而不是Python函数。