IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

C++ Discussion :

Développement d'un composant COM


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 87
    Points : 37
    Points
    37
    Par défaut Développement d'un composant COM
    Bonjour, je cherche a créer un composant utilisant la norme COM, j'ai lu et suivi le document du MSDN "The COM Programmer's Cookbook"

    lien : http://msdn.microsoft.com/library/en...sdn_com_co.asp

    J'ai créé une interface de test, j'ai compilé avec MIDL :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import "oaidl.idl";
    import "ocidl.idl";
     
    //typedef [string] char line[81]; 
     
    [ object, uuid(A46C12C0-4E88-11ce-A6F1-00AA0037DEFB) ]
    interface ITest : IUnknown
    {
        HRESULT showMessage ([in, string] char * msg);
    };
    LA compilation m'a produit 4 fichiers : dlldata.c, ITest_i.c, ITest_p.c, ITest.h

    ------------------------

    J'ai ensuite tenté de créer un contrôle qui implémenterait cette interface :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    #include <objbase.h>
    #include "ITest.h"
     
    int vcObjects = 0;
     
    // Création du composant :
    struct CMyComponent : ITest
    {
     
        // IUnknown methods
        HRESULT __stdcall QueryInterface (REFIID riid, void **ppv);
        ULONG __stdcall AddRef (void);
     
        ULONG __stdcall Release (void);
     
     
        // ITest methods
        HRESULT __stdcall showMessage( unsigned char *msg);
     
        // constructeur
        CMyComponent();
     
        // membres
        int m_cRef;
     
    };
     
     
    /***********************************************************
     * QueryInterface
     ***********************************************************/
    HRESULT CMyComponent::QueryInterface (REFIID riid, void **ppv)
    {
        if (riid == IID_IUnknown || riid == IID_ITest)
            *ppv = (ITest *) this;
        else
        {
            *ppv = 0;
            return E_NOINTERFACE;
        }    
     
     
        ((IUnknown *)*ppv)->AddRef ();
        return NOERROR;
    }
     
    /***********************************************************
     * AddRef
     ***********************************************************/
    ULONG CMyComponent::AddRef (void)
    {
        return ++ m_cRef;
    }
     
    /***********************************************************
     * Release
     ***********************************************************/
    ULONG CMyComponent::Release (void)
    {
        if (--m_cRef == 0)
        {
            --vcObjects;
     
            delete this;
            return 0;
        }
        return m_cRef;
    }
     
    /***********************************************************
     * showMessage
     ***********************************************************/
    HRESULT CMyComponent::showMessage(unsigned char *msg)
    {
        MessageBox(NULL, (LPCSTR)msg, "Message COM", MB_OK);
     
        return NOERROR;
    }
     
    /***********************************************************
     * Constructeur
     ***********************************************************/
    inline CMyComponent::CMyComponent (void)
    {
        m_cRef = 1;
        ++vcObjects;
    }
     
     
    extern "C" HRESULT CreateAvolute (IUnknown *punkOuter, REFIID riid, void **ppv)
    {
        CMyComponent *pout;
        *ppv = 0;
        if (punkOuter)
             return CLASS_E_NOAGGREGATION;
        if (!(pout = new CMyComponent))
            return E_OUTOFMEMORY;
        HRESULT hr = pout->QueryInterface (riid, ppv);
     
        pout->Release ();
        return hr;
    }
    je veux juste faire un composant qui aurait une méthode qui affiche un texte via une msgbox.

    lorsque je compile j'obtient un : error LNK2001: unresolved external symbol _IID_ITest

    IID_ITest est pourtant bien définie dans ITest.h (généré par MIDL) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    EXTERN_C const IID IID_ITest;
    je ne sais pas pourquoi il le défini en EXTERN mais visiblement ça pose pb.

    Pour info : je suis sous XP avec Visual studio 8 et j'ai créer unn projet de type DLL extended stored procedure en enlevant les fichiers relatif aux base de données, ne sachant pas quel projet chosir pour créer un composant COM.

    J'ai l'impression que des paramètres manquent dans la config de mon projet et que le linker ne si retrouve pas.

    Pour tester j'ai remplacé
    "EXTERN_C const IID IID_ITest" par "const IID IID_ITest" dans Itest.h et j'ai continué à programmer. Au moment, d'utiliser une macro microsoft faisant elle aussi appelle a des extern C ca a planté au linkage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // {A46C12C0-4E88-11ce-A6F1-00AA0037DEFB}
    DEFINE_GUID(CLSID_Avolute, 0xa46c12c0, 0x4e88, 0x11ce, 0xa6, 0xf1, 0x0, 0xaa, 0x0, 0x37, 0xde, 0xfb);
     
     
    void createComposantTest(){
     
     
        // création d'un composant COM 
        ITest *pTest;
        HRESULT hr;
        int result;
     
        // initialisation de COM
        hr = CoInitialize(NULL);
     
        hr = CoCreateInstance(CLSID_
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    MyComponent, NULL, CLSCTX_SERVER, IID_ITest, (LPVOID *)&pTest);
            // ....
            pTest->showMessage((unsigned char*)"message test");
    
    }


    Je ne comprend pas les erreurs de linkage. Déjà que je comprend pas trop COM, je galère un max là.

    julien

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 87
    Points : 37
    Points
    37
    Par défaut
    D'après UnKnown.idl (linterface mère des composant COM) dans les includes VC++ :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    cpp_quote("// IID_IUnknown and all other system IIDs are provided in UUID.LIB")
    cpp_quote("// Link that library in with your proxies, clients and servers")
    c'est donc init autre part.

    Dois je en conclure que je dois définir et initialiser mon IID_Itest qq part afin que de la même manière il soit appelé en extern dans le header généré automatiquement ?

    Pas de developpeur COM dans le forum ?

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 87
    Points : 37
    Points
    37
    Par défaut
    A tout hasard j'ai cherché IID et COm dans MSDN et visiblement il faut inclure le fichier interface_i.c, le IID est initialisé dedans

    Merci microsoft, faut tout deviner ? pas très claire la doc MIDL

  4. #4
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Citation Envoyé par inertia
    A tout hasard j'ai cherché IID et COm dans MSDN et visiblement il faut inclure le fichier interface_i.c, le IID est initialisé dedans

    Merci microsoft, faut tout deviner ? pas très claire la doc MIDL
    C'est bien dans la documentation du site que tu as donné précédemment, au tout début:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <objbase.h>
     
    #undef INTERFACE
    #define INTERFACE IFoo
     
    DECLARE_INTERFACE_ (IFoo, IUnknown)
    {
        // IUnknown methods
        STDMETHOD (QueryInterface)   (THIS_  REFIID, void **) PURE;
        STDMETHOD_(ULONG, AddRef)    (THIS) PURE;
        STDMETHOD_(ULONG, Release)   (THIS) PURE;
     
        STDMETHOD (SetValue)         (THIS_  int) PURE;
        STDMETHOD (GetValue)         (THIS_  int *) PURE;
    };
     
    // {A46C12C0-4E88-11ce-A6F1-00AA0037DEFB}
    DEFINE_GUID(IID_IFoo, 0xa46c12c0, 0x4e88, 0x11ce, 0xa6, 0xf1, 0x0, 0xaa, 0x0, 0x37, 0xde, 0xfb);
    La macro DEFINE_GUID remplit le même rôle.

  5. #5
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Forum dev windows ou VC++.
    Il y avait de très bons bouquins pour démarrer rapidement avec COM chez Wrox.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 87
    Points : 37
    Points
    37
    Par défaut
    Moldavi, en fait oui la macro de la doc déclare le GUID seulement tu remarquera que c'est pour le mec qui a déjà de l'expérience en COM et qui code direct son interface dans un .H.

    Moi j'ai utilisé MIDL qui génére tout et dans le fichier interface_i.c qui manqué la macro MIDL_CREATE_GUID où un truc comme ça est appelée, Ya 2-3 moyen de définir son interface avec COM visiblement.


    Je vais allez jetter un oeil dans le forum dev windows.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Est tu certain que lorsque tu construis ton projet tu compiles bien tous les fichiers générés par MIDL dlldata.c, ITest_i.c, ITest_p.c ?
    Et si dlldata.c se compile en une DLL séparée, est-ce que ton programme principal se link bien avec ?

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 87
    Points : 37
    Points
    37
    Par défaut
    voidSeer : je ne compile pas ITest_p.c car il me genère :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    2>f:\a-volute\dsoundhack\itest_p.c(87) : fatal error C1189: #error :  You need a Windows 2000 or later to run this stub because it uses these features:
    pourtant je suis sous XP pro SP2.
    De toute façon, il sert pour les procédure stockées je crois ?

    DllData ne se compile pas en dll. (il sert pour un code en C apparement)

    J'ai par contre 2 problèmes qui restent :

    - Mon programme de test me renvoit REGDB_E_CLASSNOTREG lors de l'appel à CoCreateInstance (CLSCTX_ALL). D'après le MSDN il semble que la classe/interface utilisée dans ma dll COM n'est pas enregistrée dans l'espace in process. J'ai vu une histoire de in-process, out-process et de DllRegister/DLL unregister dans le MSDN concernant COM. Je crois comprendre qu'a l'éxécution ma DLL doit s'enregistrer via ces deux fonctions. Les 2 fonctions sont présentes dans ma DLL mais je ne sais pas quoi y mettre.

    NB : si j'utilise CLSCTX_INPROC_SERVER dans mon CoCreateInstance j'obtiens comme code de retour : Erreur dans la DLL

    Je les ai défini ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    STDAPI DllRegisterServer()
    {
    	return NOERROR;
    }
     
    STDAPI DllUnregisterServer()
    {
    	return NOERROR;
    }
    Quelqu'un peut-il m'aider ?

    - 2eme problème :

    Lorsque je lance mon programme de test et que j'appel la fonction MessageBox ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MessageBox(NULL, (LPCWSTR)"test", NULL, MB_OK);
    le texte de ma message box apparaît sous forme de carrés, on dirait un problème d'encodage du texte. Avec ou sans _UNICODE dans le preprocesseur C++, le problème se produit. Il s'agit d'un projet Win32 Project, je suis sous VStudio 8 English (upgrade récente de ma version 2003 English)

    merci

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 87
    Points : 37
    Points
    37
    Par défaut
    En fixant Character set à "not set dans les propriétés General du projet, le projet de codage du texte est corrigé.

    Reste à comprendre l'enregistrement des infos dans le registre avec DLLRegisterServer.

    Pourtant (d'après les infos du MSDN COM cookbook) j'ai créé un fichier COMComp.reg qui contient ceci :

    REGEDIT

    HKEY_CLASSES_ROOT\Interface\{A46C12C0-4E88-11ce-A6F1-00AA0037DEFB} = ITest
    HKEY_CLASSES_ROOT\Interface\{A46C12C0-4E88-11ce-A6F1-00AA0037DEFB}\NumMethods = 1


    HKEY_CLASSES_ROOT\CLSID\{1B216C2A-D9BB-479f-8A57-27CA8D90AD70} = MyComponent
    HKEY_CLASSES_ROOT\CLSID\{1B216C2A-D9BB-479f-8A57-27CA8D90AD70}\InprocServer32 = COMTest.dll



    Curieux

  10. #10
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Je te conseille de trouver un exemple simple et complet de projet de ce type (avec un .sln ou .vcproj tout fait), de le compiler et de le tester (enregistrement et utilisation dans un programme). Si tout va bien, tu compares ce projet de test avec le tien et tu regardes ce qui est différent au niveau du code.

    Ca devrait rouler tout seul...

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 87
    Points : 37
    Points
    37
    Par défaut
    Après quelques expérimentations, j'ai remarqué que mon application cliente retrouve les bonnes informations depuis le registre : Si je renomme la dll sensé être appellée j'obtient une code erreur : "le module est introuvable".

    Si je ne renomme rien, l'application trouve la DLL et entre dans le DllMain, j'ai tracé à l'aide d'une boîte de dialogue.

    D'après MSDN et codeProject :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    hr = ::CoInitialize(NULL);
     
        hr = CoCreateInstance(CLSID_dsoundHack, NULL, CLSCTX_ALL,IID_ITest,(void**)&pTest);
     
    	if(SUCCEEDED(hr))
    		hr = pTest->showFive();
    	else
    		MessageBox(NULL, (LPCSTR)"erreur CoCreateInstance", NULL, MB_OK);
     
    CoUninitialize();
    L'appel à CoCreateInstance lit le registre via ma Clé CLSID_dsoundHack, charge la librairie si nécéssaire (ce qui manifestement se passe) et appel la fonction DllGetClassObject de la DLL. Or la MessageBox que j'ai placé au début de DllGetClassObject n'est pas appelée. On dirait qu'il y a une erreur a ce niveau mais laquelle ? J'ai pourtant respecté la signature :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void **ppv){ ... }
    Je ne dois pas être loin, ça m'énerve :s

    le code erreur renvoyé est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CO_E_ERRORINDLL
     
    EXE has error in image.

  12. #12
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 87
    Points : 37
    Points
    37
    Par défaut
    Donc en fait, en créant un fichier .def :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ; dsoundHack.def : Declares the module parameters for the DLL.
     
    LIBRARY      "dsoundHack"
    DESCRIPTION  'dsoundHack Windows Dynamic Link Library'
     
    EXPORTS
        ; Explicit exports can go here
          DllGetClassObject   @1	PRIVATE
    la méthode est appelée maintenant.
    J'ai l'impression que ce genre de paramétrage est automatique via un assistant de création de projet DLL COM microsoft VC 6.0 mais malheureusement cet assistant n'existe plus dans VC 8

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 87
    Points : 37
    Points
    37
    Par défaut
    Une bizarrie ce produit quand même :

    Mon CoCreateInstance appel bien la DllGetClassObject, celle çi crée un objet via la factory, mais sans que je l'ai demandé la méthode showFive() de mon component est éxecutée puis le programme plante (0x000000) dans ole32.dll.

    Je me demande vraiment pourquoi la méthode est appelée toute seule, et qui l'appel.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    class CMyComponent : public ITest
    {
     
    public :
     
    	// IUnknown methods
        virtual HRESULT __stdcall QueryInterface (REFIID riid, void **ppv);
        virtual ULONG __stdcall AddRef (void);
     
        virtual ULONG __stdcall Release (void);
     
     
    	// ITest methods
    	HRESULT __stdcall showFive();
     
    	// constructeur
    	CMyComponent();
     
    private :
     
    	// membres
    	int m_cRef;
     
    };
     
     
    class CMyComponentFactory : public IClassFactory
    {
     
    public :
     
    	// IUnknown methods
        virtual HRESULT __stdcall QueryInterface (REFIID riid, void **ppv);
        virtual ULONG __stdcall AddRef (void);
        virtual ULONG __stdcall Release (void);
     
    	// IClassFactory methods
    	virtual HRESULT __stdcall CreateInstance(IUnknown *pUnkOuter, const IID &riid, void** ppvObject);
    	virtual HRESULT __stdcall LockServer(BOOL flock);
     
    	CMyComponentFactory() : m_cRef(1){ }
     
    	~CMyComponentFactory() { }
     
    private :
     
    	// membres
    	int m_cRef;
    };
     
     
    HRESULT __stdcall DllGetClassObject(const CLSID& clsid, const IID& iid, void **ppv)
    {	
    	HRESULT hr;
     
    	// check le CLSID demandé par le client
    	if(clsid != CLSID_dsoundHack)
    		return CLASS_E_CLASSNOTAVAILABLE;
     
    	CMyComponentFactory *pClassFactory ;
    	pClassFactory = new CMyComponentFactory();
     
    	hr = pClassFactory->CreateInstance(NULL, IID_ITest, ppv);
     
    	printf("sortie de DllGetClassObject\n");
     
    	return hr;
    }

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Ton interface ITest est toujours en MIDL ?
    Si ce n'est plus le cas, tu pourrais la montrer?
    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.

  15. #15
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 87
    Points : 37
    Points
    37
    Par défaut
    Interface toujours en MIDL, c'est génant ?

    du côté DLL Composant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
     
     
    /* this ALWAYS GENERATED file contains the definitions for the interfaces */
     
     
     /* File created by MIDL compiler version 6.00.0366 */
    /* at Wed May 24 14:45:25 2006
     */
    /* Compiler settings for ITest.idl:
        Oicf, W1, Zp8, env=Win32 (32b run)
        protocol : dce , ms_ext, c_ext, robust
        error checks: allocation ref bounds_check enum stub_data 
        VC __declspec() decoration level: 
             __declspec(uuid()), __declspec(selectany), __declspec(novtable)
             DECLSPEC_UUID(), MIDL_INTERFACE()
    */
    //@@MIDL_FILE_HEADING(  )
     
    #pragma warning( disable: 4049 )  /* more than 64k source lines */
     
     
    /* verify that the <rpcndr.h> version is high enough to compile this file*/
    #ifndef __REQUIRED_RPCNDR_H_VERSION__
    #define __REQUIRED_RPCNDR_H_VERSION__ 475
    #endif
     
    #include "rpc.h"
    #include "rpcndr.h"
     
    #ifndef __RPCNDR_H_VERSION__
    #error this stub requires an updated version of <rpcndr.h>
    #endif // __RPCNDR_H_VERSION__
     
    #ifndef COM_NO_WINDOWS_H
    #include "windows.h"
    #include "ole2.h"
    #endif /*COM_NO_WINDOWS_H*/
     
    #ifndef __ITest_h__
    #define __ITest_h__
     
    #if defined(_MSC_VER) && (_MSC_VER >= 1020)
    #pragma once
    #endif
     
    /* Forward Declarations */ 
     
    #ifndef __ITest_FWD_DEFINED__
    #define __ITest_FWD_DEFINED__
    typedef interface ITest ITest;
    #endif 	/* __ITest_FWD_DEFINED__ */
     
     
    /* header files for imported files */
    #include "unknwn.h"
     
    #ifdef __cplusplus
    extern "C"{
    #endif 
     
    void * __RPC_USER MIDL_user_allocate(size_t);
    void __RPC_USER MIDL_user_free( void * ); 
     
    #ifndef __ITest_INTERFACE_DEFINED__
    #define __ITest_INTERFACE_DEFINED__
     
    EXTERN_C const IID IID_ITest;
     
    /* interface ITest */
    /* [uuid][object] */ 
     
    #if defined(__cplusplus) && !defined(CINTERFACE)
     
    		MIDL_INTERFACE("A46C12C0-4E88-11ce-A6F1-00AA0037DEFB")
    		ITest : public IUnknown
    		{
    		public:
    			BEGIN_INTERFACE
     
    			virtual HRESULT STDMETHODCALLTYPE showFive( void) = 0;
     
    			END_INTERFACE
     
    		};
     
    #else 	/* C style interface */
     
        typedef struct ITestVtbl
        {
            BEGIN_INTERFACE
     
            HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
                ITest * This,
                /* [in] */ REFIID riid,
                /* [iid_is][out] */ void **ppvObject);
     
            ULONG ( STDMETHODCALLTYPE *AddRef )( 
                ITest * This);
     
            ULONG ( STDMETHODCALLTYPE *Release )( 
                ITest * This);
     
            HRESULT ( STDMETHODCALLTYPE *showFive )( 
                ITest * This);
     
            END_INTERFACE
        } ITestVtbl;
     
        interface ITest
        {
            CONST_VTBL struct ITestVtbl *lpVtbl;
        };
     
     
     
    #ifdef COBJMACROS
     
     
    #define ITest_QueryInterface(This,riid,ppvObject)	\
        (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
     
    #define ITest_AddRef(This)	\
        (This)->lpVtbl -> AddRef(This)
     
    #define ITest_Release(This)	\
        (This)->lpVtbl -> Release(This)
     
     
    #define ITest_showFive(This)	\
        (This)->lpVtbl -> showFive(This)
     
    #endif /* COBJMACROS */
     
     
    #endif 	/* C style interface */
     
     
     
    HRESULT STDMETHODCALLTYPE ITest_showFive_Proxy( 
        ITest * This);
     
     
    void __RPC_STUB ITest_showFive_Stub(
        IRpcStubBuffer *This,
        IRpcChannelBuffer *_pRpcChannelBuffer,
        PRPC_MESSAGE _pRpcMessage,
        DWORD *_pdwStubPhase);
     
     
     
    #endif 	/* __ITest_INTERFACE_DEFINED__ */
     
     
    /* Additional Prototypes for ALL interfaces */
     
    /* end of Additional Prototypes */
     
    #ifdef __cplusplus
    }
    #endif
     
    #endif

    du côté client j'ai juste créer un fichier .h pour l'interface et les ID :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    #pragma once
     
    #include <objbase.h>
     
    extern "C" const IID IID_ITest ;
    extern "C" const CLSID CLSID_dsoundHack ;
     
    // ID de la classe - {1B216C2A-D9BB-479f-8A57-27CA8D90AD70}
    static const GUID CLSID_dsoundHack = { 0x1b216c2a,0xd9bb,0x479f,
    											{ 0x8a,0x57,0x27,0xca,0x8d,0x90,0xad,0x70} };
     
    // ID de l'interface
    static const IID IID_ITest = { 0xA46C12C0,0x4E88,0x11ce,
    									{ 0xA6,0xF1,0x00,0xAA,0x00,0x37,0xDE,0xFB} };
     
     
     
    // définition de l'interface ITest
    interface ITest : IUnknown
    {
     
    public:
     
    	virtual HRESULT __stdcall showFive( void) = 0;
     
    };

    J'ai testé en incluant aussi le fichier de définition d'interface à la mano et j'ai retiré les fichiers générés par MIDL ...... pareil

  16. #16
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    hum... j'avais peur que ShowFive se soit retrouvé à la place de QueryInterface dans ton ITest, mais là, ça a l'air d'aller...
    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.

  17. #17
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 87
    Points : 37
    Points
    37
    Par défaut
    Voici le main qui appel la création du composant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    int _tmain(int argc, _TCHAR* argv[])
    {
    	// création d'un composant COM 
    	ITest *pTest = NULL;
    	IClassFactory *pIClassFactory;
        HRESULT hr;
     
    	// initialisation de COM
    	hr = CoInitialize(NULL);
     
        hr = CoCreateInstance(CLSID_dsoundHack, NULL, CLSCTX_INPROC_SERVER, IID_ITest,(void**)&pTest);
     
    	if(SUCCEEDED(hr)){
    		hr = pTest->showFive();
    		pTest->Release();
    		MessageBox(NULL, (LPCSTR)"Succès !", NULL, MB_OK);
    	} else
    		MessageBox(NULL, (LPCSTR)"erreur CoCreateInstance", NULL, MB_OK);
     
     
    	// ferme la lib COM
    	CoUninitialize();
     
    	return 0;
    }
    Je suis ceratin que ma dll est appelée et que toute la fonction DllGetClassObject est exécuté (voir son code plus haut).

    Le mécanisme de factory doit normalement se charger d'initialiser le pointer passé en param pTest.

    Quand, j'éxécute en pas à pas et que j'arrive sur l'appel à CoCreateInstance, dans le debugger je lis :

    &pTest 0x0012ff60 ITest * *
    0x00000000 ITest *
    IUnknown {...} IUnknown
    __vfptr CXX0030: Error: expression cannot be evaluated


    On dirait que mon pTest n'est pas correctement init d'où le pointeur null (0x000000) qui foire tout. Où qu'il est modifié lors des traitements de la lib COM (je ne comprend pas cette erreur de méthode appelée ... )

    Ne serais ce pas là, un problème d'espace mémoire non partagé ? Ou de convention d'appel ? En tracant je suis certain qu'au moment ou DllGetObject se termine le pointeur passé en référence est valide.

    puis quelques lignes d'assembleur, puis retour dans le main et *pTest vaut encore 0x000000 et non l'@ renvoyé par le this de ma DLL.

    Précision : je suis novice en DLL


    Dois je enregistrer l'interface ITest dans le registre de la même façon que j'ai enregistré mon CLSID ? Je ne crois pas mais bon.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    REGEDIT
    HKEY_CLASSES_ROOT\Miosepayo.DsoundHack.1 = Miosepayo DsoundHack Version 1.0
    HKEY_CLASSES_ROOT\Miosepayo.DsoundHack.1\CLSID = {1B216C2A-D9BB-479f-8A57-27CA8D90AD70}
    HKEY_CLASSES_ROOT\Miosepayo.DsoundHack = Miosepayo DsoundHack
    HKEY_CLASSES_ROOT\Miosepayo.DsoundHack\CurVer = Miosepayo.DsoundHack.1
    HKEY_CLASSES_ROOT\CLSID\{1B216C2A-D9BB-479f-8A57-27CA8D90AD70} = Miosepayo DsoundHack 1.0
    HKEY_CLASSES_ROOT\CLSID\{1B216C2A-D9BB-479f-8A57-27CA8D90AD70}\InprocServer32 = F:\dsoundHack\Debug\dsoundHack.dll
    HKEY_CLASSES_ROOT\CLSID\{1B216C2A-D9BB-479f-8A57-27CA8D90AD70}\ProgID = Miosepayo.DsoundHack.1
    HKEY_CLASSES_ROOT\CLSID\{1B216C2A-D9BB-479f-8A57-27CA8D90AD70}\VersionIndependentProgID = Miosepayo.DsoundHack
     
    HKEY_CURRENT_USER\Software\Classes\Miosepayo.DsoundHack.1 = Miosepayo DsoundHack Version 1.0
    HKEY_CURRENT_USER\Software\Classes\Miosepayo.DsoundHack.1\CLSID = {1B216C2A-D9BB-479f-8A57-27CA8D90AD70}
    HKEY_CURRENT_USER\Software\Classes\Miosepayo.DsoundHack = Miosepayo DsoundHack
    HKEY_CURRENT_USER\Software\Classes\Miosepayo.DsoundHack\CurVer = Miosepayo.DsoundHack.1
    HKEY_CURRENT_USER\Software\Classes\CLSID\{1B216C2A-D9BB-479f-8A57-27CA8D90AD70} = Miosepayo DsoundHack 1.0
    HKEY_CURRENT_USER\Software\Classes\CLSID\{1B216C2A-D9BB-479f-8A57-27CA8D90AD70}\InprocServer32 = F:\dsoundHack\Debug\dsoundHack.dll
    HKEY_CURRENT_USER\Software\Classes\CLSID\{1B216C2A-D9BB-479f-8A57-27CA8D90AD70}\ProgID = Miosepayo.DsoundHack.1
    HKEY_CURRENT_USER\Software\Classes\CLSID\{1B216C2A-D9BB-479f-8A57-27CA8D90AD70}\VersionIndependentProgID = Miosepayo.DsoundHack

  18. #18
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    attends, je viens de voir la connerie: Tu ne dois pas faire de CreateInstance() dans le DllGetClassObject() : Cette fonction doit retourner un pointeur vers ta factory

    C'est windows qui se charge d'appeler CreateInstance avec le pointeur retourné.
    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.

  19. #19
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 87
    Points : 37
    Points
    37
    Par défaut
    Merci mec, j'avais point vu cette subtilité.

    T'imagines que je viens de re-installer un VC6 rien que pour l'assistant DLL COM ATL

    C'est assez vague le MSDN sur le sujet.
    Donc j'ai renvoyé mon obj factory caster en (IClassFactory *) et ça rulez ! youhou

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Langages de développement pour les Composant Com et ActiveX
    Par Pilloutou dans le forum Composants VCL
    Réponses: 1
    Dernier message: 16/08/2006, 22h59
  2. [VB] Problème composants COM Word
    Par Vince dans le forum VBA Word
    Réponses: 5
    Dernier message: 08/12/2005, 10h18
  3. Réponses: 4
    Dernier message: 03/08/2005, 14h02
  4. [C#] C# et composant COM
    Par beway dans le forum Windows Forms
    Réponses: 5
    Dernier message: 08/11/2004, 08h56
  5. Composant COM et style XP
    Par Reisubar dans le forum Composants VCL
    Réponses: 7
    Dernier message: 10/11/2003, 19h23

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