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)