Bonjour à tous et à toutes...
Le contexte : un ensemble de dlls sans code source mais avec les headers. D'après ce que j'ai lu il semble que les dlls soient compilées en Visual C++ 6.0
Cet ensemble de dlls (3) ont déjà été wrappées en Java via JNA et ça fonctionne très bien, le but est de faire le même en C++ CLI et/ou en CSharp pour attaquer ces librairies en CSharp.
Etude 1 : wrapper via un CLI
Je l'ai déjà fait.. aller go, on commence en C++ CLI, on crée un projet tout ça...
Je code, je link et là 1er problème : il n'aime pas les .lib livrés avec les dlls : xxxxxxx.lib : fatal error LNK1136: invalid or corrupt file
Je vous livre les deux batchs et le vbs qui permettent de générer un .lib au format compréhensible par Visual Studio 2015 à partir des dlls présentes dans le répertoire.
- CallVCVarsAll.bat : permet de lancer 'vcvarsall.bat' du bon visual en allant chercher le chemin d'installation en base de registre.
- GenerateDef.vbs : permet de créer le .def à partir du fichier export créé à partir de la dll.
- GenerateLibs.bat : permet de créer un .lib par dll trouvé dans le répertoire dans lequel il est exécuté.C'est ce batch qui utilise les deux autres fichiers.
Donc, je crée les .lib à partir des dlls je compile, ça link. J'accède aux variables globales présentent dans la dll (des messages d'erreurs en const char *). Et ça fonctionne !
Sitôt que je tente d'accéder à une fonction un problème se pose : le mangling.
Voir ligne 243 du fichier GenerateDef.vbs, j'ai tenté des trucs différents !
En gros, les variables globales n'ont pas de mangling et c'est pour ça que ça fonctionne... Mais pour les fonctions c'est autre chose !
1er cas : la fonction const char* HwdContextGetHwdRootPath( void );
l'export de génère :
29 1C 000094C0 _HwdContextGetConfigPath@0
Si je génère le fichier def en HwdContextGetConfigPath@0 ça link bien (dans le C++ CLI) mais lorsque je tente son chargement une erreur est générée indiquant : Le point d'entrée de la procédure HwdContextGetConfigPath@0 est introuvable dans la bibliothèque de liens dynamiques xxxxx.dll !
2ème cas : la fonction const char* HwdContextGetHwdRootPath( void );
l'export de génère :
29 1C 000094C0 _HwdContextGetConfigPath@0
Si je génère le fichier def en _HwdContextGetConfigPath@0 ça ne link plus car il y a un _ (underscore) en début du nom de la fonction, ce qui est d'ailleurs bien présent dans l'export réalisé à partir de la dll !
Les autres tests donnent les mêmes problèmes de link si je génère _HwdContextGetHwdRootPath.
J'ai tenté de faire l'import de plein de façon différente mais rien n'y fait, ce mangling fait chier !
Les pistes ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 extern "C" __declspec(dllimport) char const * __fastcall HwdContextGetHwdRootPath(void); __declspec(dllimport) char const * __fastcall HwdContextGetHwdRootPath(void); __declspec(dllimport) char const * __stdcall HwdContextGetHwdRootPath(void); extern "C" __declspec(dllimport) char const * __stdcall HwdContextGetHwdRootPath(void); __declspec(dllimport) char const * __cdecl HwdContextGetHwdRootPath(void); extern "C" __declspec(dllimport) char const * __cdecl HwdContextGetHwdRootPath(void);
- Je ne peux pas régénérer une lib d'une dll si je n'utilise pas le même compilateur que celui qui a généré la dll ?
- Il y a une façon de faire l'import pour que le mangling ne pose pas de problème et je n'ai pas trouvé comment ?
[U]Etude 2 : wrapper directement via CSharp[U]
Et là, plus besoin de lib, ça génère tout seul, ça fonctionne (en tout cas l'appel me retourne une chaîne vide).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 static class kernelhdr { [DllImport("kernelhdr.dll")] public static extern IntPtr HwdContextGetHwdRootPath(); } void main() { IntPtr toto = kernelhdr.HwdContextGetHwdRootPath(); var value = Marshal.PtrToStringAuto(toto); }
Plus simple, rapide que demande le peuple ? En plus le mangling n'a pas l'air de le déranger du tout (mais alors pourquoi ça ne fonctionne pas en C++ CLI ?).
Sauf que .... les variables globales, elles, ne sont pas accessibles dans ce mode, la chaîne HWDERR_DIGEST_FILE_READ qui est un extern "C" extern __declspec( dllexport ) char HWDDIGEST_FORMATVERSION_UNKNOWED[]; n'est pas accessible par :Ceci n'est pas autorisé par le compilateur et impossible de savoir comment accéder à une variable membre globale de la librairie, à priori on ne peut référencer que des fonctions !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 static class kernelhdr { [DllImport("kernelhdr.dll")] public static extern IntPtr HWDDIGEST_FORMATVERSION_UNKNOWED; }
Etude 3 (non réalisé) : wrapper directement via CSharp pour les fonctions et faire des LoadLibrary / GetProcAddress pour les variables globales.
Celà pourrait peut-être fonctionner mais qu'est-ce que c'est lourd !!!!
Vous avez déjà été confronté au problème ? Vous avez des pistes, au mieux une solution ? Je suis preneur !
Je ne me fais pas trop d'illusion mais j'espère trouver une solution...
Partager