python dll shared-libraries ctypes

python - lista las funciones exportadas de dll con ctypes



ctypes user32 (7)

¡SÍ! hay un método nativo muy inteligente para hacerlo.

digamos que estás usando tipos de Python. pon algo así en tu código C:

1) en tu código C:

#define PYEXPORT extern "C" __declspec(dllexport)

ahora ponga PYEXPORT arriba de la función que desea exportar:

PYEXPORT int myfunc(params){

2) Después de compilar, regrese a Python y abra su archivo .c, y analícelo de manera similar a esto:

source1_ = open(cfile_name + ''.c'') source1 = source1_.read() source1_.close() fn = source1.split(''PYEXPORT'')[-1].split(''('')[0].split('' '')[1]

entrada de shell: fn

salida de shell: ''myfunc''

3) Ahora aquí está la parte inteligente: definir una nueva función en una cadena:

a1 = """ global get_c_fn def get_c_fn(dll): func = dll.""" a2 = """ return func""" a3 = a1 + fn + a2 print(a3) global get_c_fn def get_c_fn(dll): func = dll.myfunc return func

AHORA ejecute Exec (a3) ​​y convertirá esa cadena en una función que puede usar.

4) haz lo de siempre:

mydll = ctypes.CDLL(cfile_name + ''.dll'') c_fn = get_cuda_fn(mydll) c_fn.argtypes = func_params (an array of C-converted inputs you need) c_fn( *[params] )

y allí tienes un contenedor de Python para un script en C sin tener que modificar diez cosas diferentes cada vez que algo cambia.

¿Hay alguna forma de saber qué funciones se exportan de la biblioteca de funciones extranjeras dll través de python ctypes ?

Y si es posible conocer detalles sobre las funciones exportadas a través de c types .

En caso afirmativo, ¿podría alguien proporcionar un fragmento de código?


En general, esto no es posible porque, de nuevo, en general, las bibliotecas cargadas dinámicamente no tienen la metainformación que necesita. Es posible obtener esa información en ciertos casos especiales a través de formas específicas del sistema, pero ctypes sí no ctypes esa información. Puede registrar dicha información a través de ctypes (consulte, por ejemplo, los atributos de tipo de restype y de argtypes de los punteros de función), pero solo después de haberlo obtenido por otros medios.


Internamente ctypes utiliza funciones proporcionadas por la biblioteca de enlaces dinámicos (dlopen / dlsym en Unix, LoadLibrary / GetProcAddress en Windows) para cargar la biblioteca y encontrar la dirección de la función especificada por el nombre de la función; y luego use la biblioteca cffi para pasar el parámetro dinámicamente.

El problema es que la biblioteca de vínculos dinámicos de la que depende ctypes no incluye la función para listar el símbolo de la biblioteca compartida, es por eso que no se puede listar el símbolo por ctypes.

Para hacer eso, debe usar herramientas específicas para volcar el archivo elf (readelf en Unix) y el archivo pe para dll (dumpbin en windows).


La respuesta de @ Mark usa herramientas de Visual Studio.

En Windows también puede usar Dependency Walker para obtener los nombres de las funciones de las exportaciones dll.

A veces, los nombres se destrozan y no se pueden usar como un nombre de función de python válido.

Puede usar getattr para obtener un control de las funciones mutiladas, por ejemplo:

mylib = ctypes.cdll(''mylib.dll'') my_func = getattr(mylib, ''_my_func@0'') my_func()


No creo que ctypes ofrezca esta funcionalidad. En Windows con Visual Studio:

DUMPBIN -EXPORTS XXX.DLL

O para mingw en windows:

objdump -p XXX.dll


Si está en Linux, hay una útil utilidad nm para listar el contenido de una biblioteca compartida (siempre hay una práctica utilidad en Linux, especialmente para C).

Aquí está la pregunta al respecto.

Lo usa con el indicador -D : nm -D ./libMyLib.so


Si también tiene la fuente de dicha biblioteca y está buscando una forma completamente de pitón totalmente automatizada, podría usar pycparser

para el archivo: prog.c

typedef short int ret_t; typedef short int param_t; ret_t add(param_t a, param_t b) { return (ret_t)(a + b); } ret_t passthrough(ret_t (* func)(param_t a, param_t b), param_t a, param_t b) { // parameter intentionally altered. // if this isn''t done, compiler will deem entire function redundant return func(a, b + 1); }

compilando con gcc

gcc -I. -E ./prog.c > prog-preproc.c

nos da el archivo c preprocesado: prog-preproc.c luego en python:

import pycparser parser = pycparser.c_parser.CParser() with open(''prog-preproc.c'', ''r'') as fh: ast = parser.parse(fh.read()) class FunctionVisitor(pycparser.c_ast.NodeVisitor): def visit_FuncDef(self, node): print("found function: %s" % node.decl.name) #node.show() FunctionVisitor().visit(ast)

rendimientos

found function: add found function: passthrough

Para profundizar aún más, también puede obtener tipos de parámetros y de retorno. node.show() para obtener más información desde el Árbol de sintaxis abstracta (AST)

Pronto lanzaré una biblioteca para esto (intentaré recordar volver y soltar un enlace)