Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Membre habitué

    Inscrit en
    février 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Âge : 48

    Informations forums :
    Inscription : février 2007
    Messages : 223
    Points : 160
    Points
    160

    Par défaut Wrapper CLI sur des DLL sans le code source (mais les en-têtes)

    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.
    1. CallVCVarsAll.bat : permet de lancer 'vcvarsall.bat' du bon visual en allant chercher le chemin d'installation en base de registre.
    2. GenerateDef.vbs : permet de créer le .def à partir du fichier export créé à partir de la dll.
    3. 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 !
    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);
    Les pistes ?
    • 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]
    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);
        }
    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).
    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 :
    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; 
        }
    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 !

    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...
    Fichiers attachés Fichiers attachés

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    26 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 26 964
    Points : 39 977
    Points
    39 977

    Par défaut

    Si la DLL a déjà une interface C, je serais pour la méthode 2 aussi (mais les variables globales compliquent le truc).
    Personnellement j'utiliserais la solution de facilité: Faire un wrapper pour les variables globales (avec des fonctions getter et setter pour chaque variable) dans une autre DLL non-managée, et référencer les deux DLLs depuis le C#.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre habitué

    Inscrit en
    février 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Âge : 48

    Informations forums :
    Inscription : février 2007
    Messages : 223
    Points : 160
    Points
    160

    Par défaut

    C'est un mix entre la solution 1 et 2, et ça oblige à se trimbaler deux projets (ou un projet + un fichier csharp), pourquoi pas, mais bon c'est quand même cracra !
    Surtout que je devrais pourtant réussir à tout linker correctement dans mon projet CLI !

Discussions similaires

  1. Réponses: 2
    Dernier message: 05/09/2012, 09h40
  2. Réponses: 5
    Dernier message: 17/05/2010, 22h50
  3. [PHP 5.2] Pagination sur des fichiers sans MySQL
    Par gtraxx dans le forum Syntaxe
    Réponses: 3
    Dernier message: 09/04/2009, 23h16
  4. Chargement des DLL dans le code C++
    Par Triste dans le forum C++Builder
    Réponses: 2
    Dernier message: 18/01/2008, 09h29
  5. Modifier des labels sans le code source
    Par Popof dans le forum WinDev
    Réponses: 2
    Dernier message: 12/07/2006, 11h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo