2017-07-06 7 views
1

J'essaye de concevoir un DLL externe pour mon programme de python. Maintenant, je pourrais utiliser le C++ et Visual Studio 2010 pour produire un fichier avec un postfix de ".pyd". Si le .pyd n'est pas attaché avec d'autres fichiers .dll produits par C++, cette bibliothèque python pourrait bien fonctionner.Comment activer les fonctions d'appel pyd dans une DLL C++ externe?

Cependant, maintenant je dois concevoir un fichier .pyd avec une telle struction:

A.pyd -> 1.dll -> 2.dll

dans lequel les fichiers 1,2 sont des bibliothèques C. Les fonctions de ces bibliothèques sont appelées lors de la production A.pyd.

Bien que ce fichier .pyd puisse être produit sans erreur par VS 2010, il ne pouvait pas fonctionner en python 3.6. Le rapport d'erreur est la suivante:

Traceback (most recent call last): File "<stdin> », ligne 1, en <module> ImportError: la charge de DLL a échoué, n'a pas pu trouver le programme cible

Même lorsque la référence 1.dll et 2.dll sont stockés dans le. dossier qui contient A.pyd, cette erreur existe toujours. Je me demande comment pourrais-je permettre à la bibliothèque python-C++ pour appeler les fonctions dans ces bibliothèques de liens dynamiques basées sur C.

Répondre

0

OK! Maintenant, j'ai trouvé la bonne façon d'effectuer cette opération!

Enroulez le DLL

Dans un premier temps, si la dll (je l'appelle dll-A) que vous devez appeler n'a pas exporté de fonction (vous pouvez utiliser dumpbin dans la commande VS pour vérifier les fonctions exportées), vous devez envelopper l'original dll-A. Utilisez l'appel implicite pour inclure dll-A. S'il y a une fonction déclarée dans le .h d'origine/.lib, comme ceci:

int func(int a, int b); 

Ensuite, vous devez créer un nouveau projet dll et enveloppez la fonction ci-dessus par ceci:

.h

extern "C" _declspec(dllexport) int w_func(int a, int b); 

cpp

int w_func(int a, int b){ 
    return func(a, b); 
} 

Certes, si le dumpbin montre que dll-A ont des fonctions exportables, vous pouvez passer cette étape.

Après avoir exporté cette dll (je l'appelle dll-B), vous obtiendrez dll-B 'et ses fichiers en fonction (y compris dll-A et dll-A « s en fonction des fichiers).

Écrivez le.fichier pyd

Utilisez l'appel explicite pour vous référer dll-B. Lorsque vous utilisez cette méthode, vous ne devez pas inclure de fichiers lib/.h car dll-B lui-même peut vous fournir suffisamment d'interfaces. Vous pouvez charger la dll par cette méthode:

.h

typedef int (*func_ptr)(int a, int b); 

Cpp (partie d'une fonction nommée Testdll lorsque vous écrivez le projet .pyd)

func_ptr FUNC_API = NULL; 
HINSTANCE h = LoadLibraryA("libdll/dllB.dll"); 
//Certainly! you could set the folder of stored dlls! 
if (h){ 
    FUNC_API = (func_ptr)GetProcAddress(h, "w_func"); 
    //You could load more functions here. 
} 
else{ // If the dll could not be found 
    FreeLibrary(h); 
    return 0x100; 
} 
int errorflag=0; 
if (FUNC_API==NULL){ //Check whether the function is valid. 
    cout << "Could not find: func" << endl; 
    errorflag = errorflag | 0x001; 
} 
//You could check more functions here. 
if (errorflag!=0){ // if any function could not be found. 
    FreeLibrary(h); 
    return 0x100 | errorflag; 
} 
//process functions. 
int a,b,c; 
c = FUNC_API(a,b); 
//Free the lib 
if (h) 
    FreeLibrary(h); 

Après construire votre propre .pyd, vous pourriez obtenir votre base de données python (je l'appelle pyd-C).

Lien avec le .pyd Python

En projet python, vous pouvez tester ce fichier par cette méthode:

.py

import pydC 

if __name__ == '__main__': 
    X = pydC.cclass() 
    X.Testdll(); 

Ensuite, vous pouvez constater que la fonction est bien réalisée .

A noté que votre .pyd devrait être dans le même dossier avec où .py est. Parce que vous avez défini dll-B dans libdll/dllB.dll, dll-B doit être placé dans le dossier nommé libdll. Toutefois, car dll-B appelle dll-A et d'autres DLLs implicitement, dll-A et d'autres fichiers doivent être dans votre dossier d'espace de travail, c'est-à-dire le même dossier avec où .py est.

En bref, vous devez entrer dans le dossier de l'espace de travail, et la formation du dossier est la suivante:

./ 
    Test.py 
    pydC.pyd 
    dllA.dll 
    dllA_depended1.dll 
    ... 
    libdll/ 
     dllB.dll 
+0

Si l'un de vos dll Référé est mal écrit, vous pouvez rencontrer des erreurs critiques! C'est malheureusement parce que vous ne pouvez pas être en mesure d'affiner les dlls qui dépendent. Généralement, vous pouvez écrire un programme C pour référencer explicitement la DLL exportée afin de tester si vous pouvez exécuter ces dll. Si le fichier .exe génère une erreur, il est presque inévitable de rencontrer la même erreur dans votre fichier .py. –