Bueno, se obtiene la dirección de memoria de una función compilada, pero cómo convertirla en Python llamable que se puede usar como una extensión. La respuesta a esto es el uso del módulo ctypes que puede crear un Python invocable y puede envolver una dirección de memoria arbitraria.
El siguiente código muestra cómo obtener la dirección sin procesar de bajo nivel de una función de C y cómo volver a convertirla en un objeto invocable.
Código #1:
import ctypes lib = ctypes.cdll.LoadLibrary(None) # Get the address of sin() from the C math library addr = ctypes.cast(lib.sin, ctypes.c_void_p).value print ("addr : ", addr)
Producción :
addr : 140735505915760
Código #2: Convierte la dirección en una función invocable
functype = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double) func = functype(addr) print ("Function : ", func)
Producción :
Function : <CFunctionType object at 0x1006816d0>
Código #3: llama a la función resultante
print ("func(2) : ", func(2)) print ("func(0) : ", func(0))
Producción :
func(2) : 0.9092974268256817 func(0) : 0.0
Primero se debe crear una instancia de CFUNCTYPE para que sea invocable. El primer argumento para CFUNCTYPE()
es el tipo de retorno. Los siguientes argumentos son los tipos de argumentos. Después de definir el tipo de función, se envuelve alrededor de una dirección de memoria entera para crear un objeto invocable. El objeto resultante se usa como cualquier función normal a la que se acceda a través de ctypes .
Cada vez es más común que los programas y las bibliotecas utilicen técnicas avanzadas de generación de código, como la compilación justo a tiempo, como se encuentra en bibliotecas como LLVM (LLVM en sí no es un acrónimo; es el nombre completo del proyecto).
El siguiente código usa la extensión llvmpy para hacer una función de ensamblado, obtener un puntero de función y convertirlo en un Python invocable.
Código #4:
from llvm.core import Module, Function, Type, Builder mod = Module.new('example') f = Function.new(mod, Type.function( Type.double(), [Type.double(), Type.double()], False), 'foo') block = f.append_basic_block('entry') builder = Builder.new(block) x2 = builder.fmul(f.args[0], f.args[0]) y2 = builder.fmul(f.args[1], f.args[1]) r = builder.fadd(x2, y2) builder.ret(r)
Producción :
<llvm.core.Instruction object at 0x10078e990>
Código #5:
from llvm.ee import ExecutionEngine engine = ExecutionEngine.new(mod) ptr = engine.get_pointer_to_function(f) ptr
Producción :
4325863440
Código #6: llama a la función resultante
foo = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double, ctypes.c_double)(ptr) print (foo(2, 3)) print ("\n", foo(4, 5)) print ("\n", foo(1, 2))
Producción :
13.0 41.0 5.0
Publicación traducida automáticamente
Artículo escrito por manikachandna97 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA