Wie deklariert man ein COM interface?



  • Hallo.

    Wie der titel schon sagt: Wie deklariert man ein COM interface?

    Sobald ich das schlüsselwort 'interface' in einen header eintrage, behauptet er ich müsse ein ';' danach machen:

    interface ITest
    {   
        void P1();
        void P2();
    }
    

    Die hilfe zu dem thema ist auch nicht gerade übersichtlich. Und vor allem wo und wie deklariere ich die IID (GUID)?

    Ich finde einfach keine gute anleitung zu dem thema! Vielleicht wisst ihr welche?

    vielen dank 🙂 ..maximov



  • am besten über Einfügen-> neues ATL-Objekt usw.
    Dann macht VS alles von alleine und du kannst dann dein Interface bestücken.
    So long...

    Ciao,

    Stalin



  • in C++ als class, die von IUnknown ableitet und nur virtuell abstrakte methoden enthält, sonst nix. Rückgabewert zumeist HRESULT, ist aber nicht 100% zwingend. parameter müssen COM-Kompatibel sein.

    class IFoo : public IUnknown
    {
      public:
        HRESULT Foo() = 0;
        HRESULT Bar() = 0;
    };
    

    Wenn jemand anders dein Interface auch kennen soll, dann reicht das natürlich nicht 😉

    IDL ist eine Beschreibungssprache für interfaces, die es erlaubt die notwendigen Marshalling-Zusatzinformationen (die man in C++ nicht angeben kann) anzugeben. der MIDL Compiler kann dir daraus dann machen:
    - eine Typbibliothek (.tlb, die kann man dann "überall" reinziehen)
    - C/C++ header
    - Ein Proxy/Stub-Projekt für Cross-Apartment-Marshalling

    Das einfachste ist natürlich, man nimmt den ATL Wizard, wie schon vorgeschlagen 😉



  • struct IMyInterface : public IUnknown
    {
        STDMETHOD_(type) MyMethod1() = 0;
        STDMETHOD_(type) MyMethod2() = 0;
    };
    

    So, oder so ähnlich, wird das mit MFC gemacht, ohne ATL



  • Aha...danke schonmal! Das >public: IUnknown< war die info die ich brauchte 🙂

    ATL etc. kommt leider nicht in frage da die dll in einer anderen sprache erzeugt wurde 😉 ...deshalb habe ich auch keinen header, womit ich auch schon beim nächsten problem wäre:

    Und zwar habe ich eine factory function exportiert, die mir einen pointer auf eine gültige instanze zurück gibt. Beim blind importieren, in vc++, bekomme ich allerdings probleme:

    #ifdef EXPORTS
    #define MX __declspec(dllexport) __stdcall
    #else
    #define MX __declspec(dllimport) __stdcall
    #endif
    #define STDCALL __stdcall
    
    class ITest: public IUnknown 
    {
    public:
      virtual void P1() = 0;
      virtual void P2() = 0;
    };
    
    extern "C" ITest* MX CreateTest();
    

    error LNK2001: Nichtaufgeloestes externes Symbol _CreateTest@0

    Meine frage wäre hier, wenn der header den selber namen wie die DLL hat, wird der bezug dann automatisch hergestellt? ...oder wie kann ich das statisch linken, sodass das symbol aufgelöst werden?

    mfg. maximov.



  • beschreib mal bite genauer was du machen willst, eh' wir uns auf die falsceh Fährte verirren.

    um ein COM-Objekt zu nutzen kannst du entweder:

    - in MFC Clazz Wizard "Add Class/from type library" verwenden
    - mit #import die type libary des objekts reinziehen

    ich bevorzuge #import, arbeitet aber mit exceptions.



  • Langsam komme ich der sache schon näher!

    Ich hab jetzt eine .tlb die ich mit #import reinziehe. Er generiert mir auch brav einen header dafür -> .tlh! Aber wenn ich dann mein interface nutzen will, sagt er, dass die klasse nicht definiert ist! ??

    Ich hab aber auch eine .idl:

    [
      uuid(D00A1D1E-9E40-4B30-A6BE-780CED4435A7), 
      lcid(0x075BCD15), 
      version(1.0), 
      helpstring("crossroad Bibliothek")    
    ]
    library crossroad
    {
      importlib("stdole2.tlb");
      [
        uuid(205BC04F-66FA-4A44-A277-DBF936861E34), 
        version(1.0), 
        helpstring("Schnittstelle für TCross Objekt"), 
        dual, 
        oleautomation
      ]
       interface ICross: IDispatch
      {
        [
        id(0x000000C9)
        ]
        HRESULT _stdcall P1( void );
        [
        id(0x000000CA)
        ]
        HRESULT _stdcall P2([in] int Param1 );
      };
      [
        uuid(9C6AF351-017B-4FD7-9CEE-6340E04E494D), 
        version(1.0), 
        helpstring("TCross")
      ]
      coclass TCross
      {
        [default] interface ICross;
      };
    };
    

    Kann man damit vielleicht was machen?

    Dann hab ichs noch mit dem klassen assistenten versucht...ging auch sehr gut -> klasse hinzufügen -> aus typbibl.. -> dann hat er direkt aus der dll das interface erkannt und mir einen header ins projekt gebunden! Nur leider konnte dann wieder ein externes symbol nicht auflösen 😞

    error LNK2001: Nichtaufgeloestes externes Symbol "public: void __thiscall ICross::P1(void)" (?P1@ICross@@QAEXXZ)

    Wie ist denn der zusammenhang von meiner anwendung zu der DLL mit dem interface?

    danke an alle und im vorraus 🙂

    PS: Wo wird beim linken nach symbolen gesucht? auch in DLLs? wenn nicht wäre das ja auch kein wunder! In libs? kann man vielleicht aus ner IDL oder TLB eine lib gerenieren?

    cu. maximoi





  • Jaaa! Es geht 🙂 Vielen dank für den tip. So kompliziert is das alles garnicht, hatte nur paar schwierigkeiten die definition in c++ richtig hinzubekommen 😉

    Danke.

    cu. maximov.


Anmelden zum Antworten