Wer räumt den Speicher auf?



  • Hallo Forum,

    ich habe diesen ATL COM Getter erstellt. Es wird eine neues Objekt CAtlPerson erstellt und über COM von meiner C++ Anwendung an eine VBA Anwendung geschickt:

    STDMETHODIMP CAtlCompany::GetCustomer(IAtlPerson** Customer) {
    	HRESULT hres;
    	void *tmp=0;
    
    	hres = CoInitializeEx(0, COINIT_MULTITHREADED); // COM initialisieren.
    	hres = CoCreateInstance(CLSID_CAtlPerson, 0, CLSCTX_SERVER, IID_IAtlPerson, &tmp); // Neue Klasseninstanz erstellen.
    	if (hres == S_OK) {
    		CAtlPerson *oPerson = (CAtlPerson *)tmp; // Objekt hinter dem Interface setzen.
    		oPerson->SetObj(m_oCompany.GetPerson()); // Daten in das zu erstellende Objekt einfügen
    		*Customer = (IAtlPerson *)oPerson; // Zeiger für den Rpckgabewert setzen.
    	}
    	CoUninitialize(); // COM wieder freigeben.
    
    	return S_OK;
    }
    
    __interface IAtlCompany : IDispatch {
    	[id(1), helpstring("method GetCustomer")] HRESULT GetCustomer([out,retval] IAtlPerson** Customer);
    };
    

    Weiß jemand wan die Instanz von CAtlPerson wieder zerstört wird?

    Vielen Dank

    Bommel



  • Das CoInitializeEx und CoUninitialize hat da drinnen nix verloren.
    U
    nd die Objekte werden über reference counting verwaltet (AddRef, Release), d.h. das Objekt wird automatisch freigegeben wenn sämtliche Interfaces darauf keine "Referenzen mehr haben".
    Wenn du ein Interface als [out] Parameter hast, dann musst du es immer so zurückgeben dass der Aufrufer eine "Referenz" mitbekommt, d.h. der Aufrufer muss nach dem deine Funktion zurückgekehrt ist irgendwo Release() aufrufen um das Interface freizugeben.
    Eben gleich wie es auch bei QueryInterface oder allen anderen COM Funktionen ist die Interfaces als [out] Parameter haben.

    Du solltest IMO hier auch nicht CoCreateInstance verwenden, sondern direkt new CAtlPerson.



  • CAtlPerson ist eine abstrakte Klasse. Wenn ich es versuche:

    'HRESULT CAtlPerson::QueryInterface(const IID &,void ** ) throw()': Rein virtuelle Funktion wurde nicht definiert
    z:\aa\AtlCompany.h(31): Siehe Deklaration von 'CAtlPerson::QueryInterface'

    1. Wo bringst Du CoInitializeEx in einem VS 2003 ATL DLL Projekt unter?
    2. Wenn ich versuche eine neue Funktion der Form:

    GetCustomer2(IAtlPerson &Customer)
    

    Will das der Assistent nicht schlucken. Mit Referenz meinst Du keine C++ Referenz?



  • Zu 2.)
    Funktionen am COM-Interface kennen keine Parameterübergabe mittel C++-Referenz (&)
    du musst dich schon mit * und ** begnügen. 🙂



    1. Hat sich durch Dein anderes Posting auch erledigt.
      Danke 🙂


  • Er, ja, du kannst nicht einfach CAtlPerson instanzieren, da gibts ATL helper-templates die du verwenden musst: http://msdn2.microsoft.com/en-us/library/c43h4867(VS.71).aspx
    Vorausgesetzt du verwendest nirgends aggregation müsste es so gehen:

    IMyInterface* p = new CComObject<CMyClass>();
    // Reference-Count des neuen Objektes ist 0, wir brauchen aber 1, also 1x AddRef
    p->AddRef();
    

    Dadurch vermeidest du Probleme wenn CLSID_CAtlPerson z.B. falsch oder garnicht registriert sein sollte. Da du das Objekt selbst anlegst kannst du z.B. auch ganz darauf verzichten CLSID_CAtlPerson irgendwo zu registrieren, dann kann man es nurmehr über die GetCustomer Funktion anlegen (wenn das gewünscht sein sollte).

    Und ja, mit dass der Aufrufer eine "Referenz" mitbekommt meinte ich dass du dem Aufrufer ein Interface zurückgibst dessen Reference-Count 1 ist -- so dass er eben 1x Release aufrufen muss um es freizugeben.



  • Hat dem Getter viel an Komplexität genommen. Vielen Dank 🙂


Log in to reply