none
Créer Dll C++ pour projet C# RRS feed

  • Question

  • Bonjour,

    J'ai besoin de votre aide, voila mon problème:

    J'ai à disposition un .lib et son .h, sans avoir les sources, et avec ces deux fichier je doit pouvoir utiliser les fonctions de la lib dans un projet C#, je sais que ce n'est pas faisable directement (ou alors je vais pleurer ^^).

    En tout cas voila comment sa se présente (je vais prendre qu'une seule fonction en exemple):

    Voila le header:

    #ifdef __cplusplus
    extern "C" {
    #endif
    
    extern int APIENTRY SID_Open(BOOL 	fReadImages);

    Mon programme en C++:

    #include "Sid.h" #pragma comment( lib ,"SID.lib") __declspec(dllexport) int SID_Open(bool fRead) { return SID_Open(true);

    }

    Mon programme C# qui est censé récupérer la fonction SID_Open:

    [DllImport("Dll.dll", EntryPoint = "#1")]
    internal static extern double Open();

    Voila ou j'en suis, mon programme C# récupère bien la fonction SID_Open déclarer en C++ et l'éxécute bien (tester sur console).

    Cependant mon problème vient du programme C++ en lui même je n'arrive pas à récupérer la fonction du .lib, si je fais comme dans l'extrait plus haut le programme s'appelle lui même du au même nom. Et si je change le nom en (par exemple)  __declspec(dllexport) int Open(bool fRead), mon programme C# ne trouve plus la Dll créer.

    Je tiens également à préciser que mon niveau de codage est insuffisant pour ce problème, mais bon pas le choix.

    Je vous remercie par avance de l'aide que vous pourriez m'apporter.

    Cordialement

    mardi 21 février 2012 15:02

Réponses

  • Désolé pour la coquille qui à fait disparaître le "__de" de mon code. :-(

    L'erreur de link et le contenu du fichier header me fait entrevoir la fin du tunnel. :-)

    L'erreur de link montre que votre lib "SID.lib" n'exporte pas en C++ ces fonctions, c'est un bon point.

    Je suppose donc que la lib les exporte en C.

    Le contenu du fichier d'en-tête montre qu'il n'y a pas de marquage qui spécifie un export en C. C'est logique pour un compilateur C mais votre projet est C++ pas C.

    Le marquage ce fait tout simplement avec extern "C" {...}.

    Donc le code suivant devrait être plus proche de la cible.

    #include "windows.h"
    #pragma comment( lib ,"SID.lib")
    extern "C"
    {
    #include "Sid.h"
    
     __declspec(dllexport) int MySID_Open(bool fRead)
    {
    	return SID_Open(true);
    };
    }


    Paul Bacelar, Ex - MVP VC++

    jeudi 23 février 2012 10:05
    Modérateur
  • Bonjour,

    Ce code est bien compilé mais le projet C# annonce une Dll introuvable alors qu'en faisant un return 0 la Dll fonctionne.

    j'ai réussi à me procurer une dll en VB6 que je peux directement utiliser dans mon projet de la manère suivante:

    [DllImport("SID.dll", EntryPoint = "#1",PreserveSig = true)]
    internal static extern int Open(bool a);

    Mon problème est donc résolut ^^

    En tout cas merci de votre aide.

    Cordialement

    jeudi 23 février 2012 13:26
  • Au vue des problèmes que vous avez eu après mes dernières suggestions.

    (Les problèmes ont été exposés dans un message que Lesourd Cyril a supprimer depuis.)

    Comme le  fait que dependency walker indique une SID.dll introuvable, cela fait écho à mon message premier message :

    >> J'ai à disposition un .lib et son .h, sans avoir les sources, et avec ces deux fichier je doit pouvoir utiliser les fonctions de la lib dans un projet C#, je sais que ce n'est pas faisable directement (ou alors je vais pleurer ^^).

    >Si, si c'est une lib de Dll, mais il faut bien connaître .NET le C et Windows, mais surtout que les développeurs n'ait pas fait trop de conneries comme faire des exports C++ à la place d'export C.

    Et bien je pense que vous pouvez pleurer, si l'on n'est bien en présence d'une Dll qui exporte avec les conventions C (qu'elle ait été généré par VC++ ou autre chose importe peu) vous n'avez pas besoin, ni du fichier lib, ni du fichier .h, ni de la Dll C++. Mais de faire exactement comme avec le Dll VB (qui est peut-être la Dll SID.dll cherché par dependency walker).


    Paul Bacelar, Ex - MVP VC++

    jeudi 23 février 2012 14:24
    Modérateur

Toutes les réponses

  • Et si je change le nom en (par exemple)  __declspec(dllexport) > int Open(bool fRead), mon programme C# ne trouve plus la Dll créer

    Le changement de nom d'une fonction ne devrait pas empécher Dll.dll d'être générée et chargée par le programme C#. 

    Est-ce que Dll.dll est bien générée au même endroit dans les deux cas ?

    Pour info, il existe un petit programme gratuit, Dependency Walker, qui permet d'ouvrir un fichier DLL et de regarder quelles sont les fonctions exportées par cette DLL. http://www.dependencywalker.com/

    mardi 21 février 2012 16:21
    Auteur de réponse
  • Bonjour,

    Pour Dependency walker j'ai bien ma fonction:

    ?SID_Open@@YAH_N@Z
    int SID_Open(bool) (si je coche undecorate c++ function)

    Sinon j'ai quand même deux erreurs de remontées mais qui n'ont pas l'air d'influer sur le fonctionnement:

    MSVCR90D.DLL introuvable (Microsoft® C Runtime Library, v. 9.0.30729.1)

    IESHIMS.DLL introuvable (Internet Explorer Compatibility Shims, Windows® Internet Explorer)

    Sinon au niveau du fonctionnement c'est vraiment étrange:

    #include "windows.h"
    #include "Sid.h"
    #pragma comment( lib ,"SID.lib")
    __declspec(dllexport) int SID_Open(bool fRead)
    {
    	return 0;
    	//return SID_Open(true);
    };

    Avec ce code la je produit bien ma dll, je la déplace dans le bin de mon prjet C# et en debugant le projet je récupère bien mon 0 ^^

    Mais comme sa:

    __declspec(dllexport) int SID_Open(bool fRead)
    {
    	//return 0;
    	return SID_Open(true);
    };

    Le programme créer un boucle infinie, mais mon prjet C# récupère bien la dll et indique l'exception

    Et le soucis vien de ce code la:

    __declspec(dllexport) int Open(bool fRead)
    {
    	//return 0;
    	return SID_Open(true);
    };
    

    Donc je change le nom de l'export pour eviter la boucle infini, je produit bien la dll sans erreurs, je la déplace au même endroit que les autres et la exception à l'éxécution du C# : Impossible de charger la DLL 'Dll.dll': Le module spécifié est introuvable. 

    J'ai éssayer de produire la dll en debug et en release même résultat.

    La je comprend pas, à noter que j'ai tout les réglages de base sinon.

    Si quelqu'un à une idée je suis preneur ^^.

    Cordialement

    mercredi 22 février 2012 09:17
  • Rebonjour,

    J'ai un peu avancer, ou reculer ^^:

    extern "C" int SID_Open(bool fReadImages);
    
    extern "C"
    {
    __declspec(dllexport) int Open(bool T)
    {  
    	return SID_Open(T);  
    };
    }

    Ce code me remonte une erreur:

    1>DllCode.obj : error LNK2019: symbole externe non résolu _SID_Open référencé dans la fonction _Open
    1>C:\Users\cyril.lesourd\Documents\Visual Studio 2008\Projects\Dll\Debug\Dll.dll : fatal error LNK1120: 1 externes non résolus

    Voila mais sinon je bloque toujours ^^.

    mercredi 22 février 2012 11:15
  • On reprend.

    > J'ai à disposition un .lib et son .h, sans avoir les sources, et avec ces deux fichier je doit pouvoir utiliser les fonctions de la lib dans un projet C#, je sais que ce n'est pas faisable directement (ou alors je vais pleurer ^^).

    Si, si c'est une lib de Dll, mais il faut bien connaître .NET le C et Windows, mais surtout que les développeurs n'ait pas fait trop de conneries comme faire des exports C++ à la place d'export C.

    Pouvez-vous poster toute ou partie de leur .h ?

    Vous semblez pas trop maitriser le noms de fonctions les namespaces, les namespaces implicites et le mangling C++. Alors on va faire simple, utilisez des noms différents entre les fonctions/méthodes exportés de votre Dll et les noms des fonctions de la lib.

    Pour simplifier encore, utilisez les conventions de mangling C et non C++ aussi pour les fonctions que vous exportez de la Dll.

    #include "windows.h" #include "Sid.h" #pragma comment( lib ,"SID.lib")

    extern "C"
    {
    clspec(dllexport) int MySID_Open(bool fRead) { return SID_Open(true); };

    }

    Notez le "#pragma comment( lib ,"SID.lib")" qui indique à VS d'utiliser SID.lib à l'édition de lien. C'est le motif de l'erreur LNK2019. (il y a plus propre mais chacun ses goûts)

    [DllImport("Dll.dll", EntryPoint = "MySID_Open")]
    internal static extern double Open();


    Paul Bacelar, Ex - MVP VC++

    mercredi 22 février 2012 13:39
    Modérateur
  • Tout d'abord merci pour votre aide,

    Voici pour commencer une partie de mon header qui ne contient rien d'autre d'intéréssant, juste deux structures et des defines:

    #ifndef SID_H
    #define SID_H     1
    
    extern int APIENTRY SID_Open(BOOL 	fReadImages);
    
    extern int APIENTRY SID_Initialize();
    
    extern int APIENTRY SID_Close();
    
    extern int APIENTRY SID_GetVersion(char *String,short Length);
    
    ect...... (plein de déclaration)
    
    #endif

    Sinon le code C que vous proposez, je récupère des erreurs de link:

    #include "windows.h"
    #include "Sid.h"
    #pragma comment( lib ,"SID.lib")
    
    extern "C"
    {
     __declspec(dllexport) int MySID_Open(bool fRead)
    {
    	return SID_Open(true);
    };
    }
    Erreur:
    1>DllCode.obj : error LNK2019: symbole externe non résolu "int __stdcall SID_Open(int)" (?SID_Open@@YGHH@Z) référencé dans la fonction _MySID_Open
    1>C:\Users\cyril.lesourd\Documents\Visual Studio 2008\Projects\Dll\Debug\Dll.dll : fatal error LNK1120: 1 externes non résolus

    Par contre j'ai mis __declspec au lieu de clspec comme vous proposier parce que la commande n'étais pas reconnu.


    mercredi 22 février 2012 14:52
  • Désolé pour la coquille qui à fait disparaître le "__de" de mon code. :-(

    L'erreur de link et le contenu du fichier header me fait entrevoir la fin du tunnel. :-)

    L'erreur de link montre que votre lib "SID.lib" n'exporte pas en C++ ces fonctions, c'est un bon point.

    Je suppose donc que la lib les exporte en C.

    Le contenu du fichier d'en-tête montre qu'il n'y a pas de marquage qui spécifie un export en C. C'est logique pour un compilateur C mais votre projet est C++ pas C.

    Le marquage ce fait tout simplement avec extern "C" {...}.

    Donc le code suivant devrait être plus proche de la cible.

    #include "windows.h"
    #pragma comment( lib ,"SID.lib")
    extern "C"
    {
    #include "Sid.h"
    
     __declspec(dllexport) int MySID_Open(bool fRead)
    {
    	return SID_Open(true);
    };
    }


    Paul Bacelar, Ex - MVP VC++

    jeudi 23 février 2012 10:05
    Modérateur
  • Bonjour,

    Ce code est bien compilé mais le projet C# annonce une Dll introuvable alors qu'en faisant un return 0 la Dll fonctionne.

    j'ai réussi à me procurer une dll en VB6 que je peux directement utiliser dans mon projet de la manère suivante:

    [DllImport("SID.dll", EntryPoint = "#1",PreserveSig = true)]
    internal static extern int Open(bool a);

    Mon problème est donc résolut ^^

    En tout cas merci de votre aide.

    Cordialement

    jeudi 23 février 2012 13:26
  • Au vue des problèmes que vous avez eu après mes dernières suggestions.

    (Les problèmes ont été exposés dans un message que Lesourd Cyril a supprimer depuis.)

    Comme le  fait que dependency walker indique une SID.dll introuvable, cela fait écho à mon message premier message :

    >> J'ai à disposition un .lib et son .h, sans avoir les sources, et avec ces deux fichier je doit pouvoir utiliser les fonctions de la lib dans un projet C#, je sais que ce n'est pas faisable directement (ou alors je vais pleurer ^^).

    >Si, si c'est une lib de Dll, mais il faut bien connaître .NET le C et Windows, mais surtout que les développeurs n'ait pas fait trop de conneries comme faire des exports C++ à la place d'export C.

    Et bien je pense que vous pouvez pleurer, si l'on n'est bien en présence d'une Dll qui exporte avec les conventions C (qu'elle ait été généré par VC++ ou autre chose importe peu) vous n'avez pas besoin, ni du fichier lib, ni du fichier .h, ni de la Dll C++. Mais de faire exactement comme avec le Dll VB (qui est peut-être la Dll SID.dll cherché par dependency walker).


    Paul Bacelar, Ex - MVP VC++

    jeudi 23 février 2012 14:24
    Modérateur