liste des fonctions exportées de dll avec ctypes

y a-t-il un moyen de savoir quelles fonctions sont exportées de la dll par la bibliothèque de fonctions étrangères python ctypes ?

et si possible de connaître les détails sur les fonctions exportées à travers c types .

dans l'affirmative, quelqu'un pourrait-il fournir un extrait de code?

31
demandé sur xealits 2010-05-23 15:22:12

7 réponses

Je ne pense pas que les ctypes offrent cette fonctionnalité. Sous Windows avec visual studio:

DUMPBIN -EXPORTS XXX.DLL

ou pour mingw sur windows:

objdump -p XXX.dll
15
répondu Mark 2010-05-23 14:37:45

si vous êtes sous Linux, il y a un utilitaire pratique nm pour lister le contenu d'une bibliothèque partagée (il y a toujours un utilitaire pratique sous Linux, surtout pour les choses en C.)

Voici la question à ce sujet.

vous l'utilisez avec le drapeau -D : nm -D ./libMyLib.so

9
répondu xealits 2017-05-23 12:18:18

en général, ce n'est pas possible, parce que, encore une fois en général, les bibliothèques chargées dynamiquement ne contiennent pas les méta-informations dont vous avez besoin. Il est peut-être possible d'obtenir cette information dans certains cas particuliers par des moyens propres au système, mais ctypes lui-même ne recueille pas cette information. Vous pouvez enregistrer telles informations via ctypes (voir par exemple les attributs restype et argtypes des pointeurs de fonction), mais seulement après vous les avez obtenus par des moyens différents.

6
répondu Alex Martelli 2010-05-23 14:40:41

@Mark's answer utilise Visual Studio tools.

sous windows, vous pouvez également utiliser Dependency Walker pour obtenir les noms de fonction des exportations dll.

parfois les noms sont déformés et ne peuvent pas être utilisés comme nom de fonction python valide.

vous pouvez utiliser getattr pour obtenir une poignée à fonctions mutilées, E. g:

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

my_func()
4
répondu Peter Wood 2014-11-03 10:00:48

si vous avez aussi la source de ladite bibliothèque, et que vous êtes à la recherche d'un tout-Python entièrement automatisé, vous pouvez utiliser pycparser

pour le fichier: 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);
}

compilant avec gcc

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

nous donne le fichier c pré-traité: prog-preproc.c puis 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)

rendements

found function: add
found function: passthrough

pour creuser plus loin vous pouvez aussi obtenir les types de paramètre et de retour. Décommenter node.show() pour plus d'informations à partir de l'intérieur de l'Arbre de Syntaxe Abstraite (AST)

je vais libérer une bibliothèque pour cela bientôt (je vais essayer de me rappeler de revenir et de laisser tomber un lien)

1
répondu FraggaMuffin 2017-01-19 08:05:37

en interne, ctypes utilise des fonctions fournies par la bibliothèque de lien dynamique (dlopen/dlsym sur unix, LoadLibrary / Getrocaddress sur windows) pour charger la bibliothèque et trouver l'adresse de la fonction spécifiée par le nom de la fonction; et puis utiliser la bibliothèque cffi pour passer le paramètre de manière dynamique.

le problème est que la bibliothèque de liens dynamiques dont dépend ctypes n'inclut pas de fonction pour lister le symbole de la bibliothèque partagée, c'est pourquoi vous ne pouvez pas lister le symbole par ctypes.

pour ce faire, vous devez utiliser des outils spécifiques pour Dumper le fichier elf (readelf sur unix) et le fichier pe Pour dll (dumpbin sur windows).

0
répondu Sam Liao 2014-12-03 14:05:34

Oui! il y a une méthode autochtone très intelligente pour le faire.

disons que vous utilisez des ctypes Python. mettez quelque chose comme ça dans votre code C:

1) dans votre code C:

#define PYEXPORT extern "C" __declspec(dllexport)

mettez maintenant PYEXPORT au-dessus de la fonction que vous voulez exporter:

PYEXPORT
int myfunc(params){

2) Après la compilation, retournez en Python et ouvrez votre .c fichier, et l'analyse semblable à ceci:

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

entrée shell: fn

sortie shell: 'myfunc'

3) Maintenant voici la partie intelligente: définir une nouvelle fonction dans une chaîne de caractères:

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

MAINTENANT que exec(a3) et il va transformer cette chaîne en une fonction que vous pouvez utiliser.

4) Faire comme d'habitude:

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] )

et là vous avez un wrapper python pour un script C sans avoir à modifier dix choses différentes chaque fois que quelque chose change.

0
répondu Chant 2018-03-08 04:12:06