Com-Automation-Server mit einem Interface als Property



  • Hallo,

    Ich erstelle gerade einen Com-Automation-Server und habe Probleme mit verschachtelten Interfaces (Ein Interface hat ein anderes als Property). Wenn ich nun das Feld "Wert" des Subinterfaces setzen will, dann knallt das Programm (da das Interface anscheinend nicht mehr gültig ist). Wenn ich allerdings in der Get-Methode ein AddRef() auf das Subinterface hinzufüge, dann klappt es. Dann werden allerdings beim Beenden des Programms die Interfaces nicht mehr freigegeben und es entstehen Speicherlecks. Ich denke das Problem liegt irgendwo bei meinem Get/Set-Methoden. Kann mir da jemand weiterhelfen?

    Viele Grüße Wurst

    Mein Interface sieht ungefähr so aus:

    ---- meinPseudo.idl ----
    
    [uuid(<eine guid>)]
    library MeinServerLib
    {
    
      	[uuid(<eine guid>), odl, version(1.0), dual, oleautomation]
    	interface IMeinSubInterface : IDispatch
    	{
            	[id(1), propget] HRESULT Wert([out, retval] BSTR* value);
    	        [id(1), propput] HRESULT Wert([in] BSTR value);
    	}
    
    	[uuid(<eine guid>)]
    	coclass MeinSubInterface
    	{
    		[default] interface IMeinSubInterface;
    	};
    
      	[uuid(<eine guid>), odl, version(1.0), dual, oleautomation]
    	interface IMeinInterface : IDispatch
    	{
            	[id(1), propget] HRESULT MeinSubinterface([out, retval] IMeinSubInterface** value);
    	        [id(1), propput] HRESULT MeinSubinterface([in] IMeinSubInterface* value);
    	}
    
    	[uuid(<eine guid>)]
    	coclass MeinInterface1
    	{
    		[default] interface IMeinInterface;
    	};
    }
    
    ---- meinPseudo.idl Ende ----
    
    ---- MeinInterface.cpp ----
    
    IMPLEMENT_DYNCREATE(CMeinInterface, CCmdTarget)
    
    CMeinInterface::CMeinInterface()
    {
    	EnableAutomation();
    	AfxOleLockApp();
    }
    
    CMeinInterface::~CMeinInterface()
    {
    	AfxOleUnlockApp();
    }
    
    void CMeinInterface::OnFinalRelease()
    {
    	CCmdTarget::OnFinalRelease();
    	m_meinSubInterface->Release();
    }
    
    BEGIN_MESSAGE_MAP(CMeinInterface, CCmdTarget)
    END_MESSAGE_MAP()
    
    BEGIN_DISPATCH_MAP(CMeinInterface, CCmdTarget)
    	DISP_PROPERTY_EX_ID(CMeinInterface, "MeinSubinterface", 1, get_MeinSubinterface, put_MeinSubinterface, VT_DISPATCH)
    END_DISPATCH_MAP()
    
    BEGIN_INTERFACE_MAP(CMeinInterface, CCmdTarget)
    	INTERFACE_PART(CMeinInterface, IID_IMeinInterface, LocalClass)
    END_INTERFACE_MAP()
    
    IMPLEMENT_OLECREATE(CMeinInterface, "MeinServer.MeinInterface", ... guid ...)
    
    IMeinSubInterface* CMeinInterface::get_MeinSubinterface(void)
    {
    	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    		//m_meinSubInterface->AddRef();
    	return m_meinSubInterface;
    }
    
    void CMeinInterface::put_MeinSubinterface(IMeinSubInterface* newVal)
    {
    	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    	m_meinSubInterface = newVal;
    	m_meinSubInterface->AddRef();
    }
    
    ...
    
    STDMETHODIMP CMeinInterface::XLocalClass::get_uom(IMeinSubInterface** value)
    {
        METHOD_PROLOGUE(CMeinInterface, LocalClass)
        *value = pThis->get_MeinSubinterface();
        return S_OK;
    }
    
    STDMETHODIMP CMeinInterface::XLocalClass::put_uom(IMeinSubInterface* value)
    {
        METHOD_PROLOGUE(CMeinInterface, LocalClass)
        pThis->put_Meinsubinterface(value);
        return S_OK;
    }
    
    ---- MeinInterface.cpp Ende ----
    
    ---- MeinInterface.h ----
    
    class CMeinInterface : public CCmdTarget
    {
    	DECLARE_DYNCREATE(CMeinInterface)
    
    public:
    	CMeinInterface();
    	virtual ~CMeinInterface();
    	virtual void OnFinalRelease();
    
    protected:
    	DECLARE_MESSAGE_MAP()
    	DECLARE_OLECREATE(CMeinInterface)
    	DECLARE_DISPATCH_MAP()
    	DECLARE_INTERFACE_MAP()
    
    public:
    	IMeinSubInterface* m_meinSubInterface;
    
    	IMeinSubInterface* get_MeinSubinterface(void);
    	void put_MeinSubinterface(IMeinSubInterface* newVal);
    
    	BEGIN_INTERFACE_PART(LocalClass, IMeinInterface)
    		...
    		STDMETHOD(get_MeinSubinterface)(IMeinSubInterface** newVal);
    		STDMETHOD(put_MeinSubinterface)(IMeinSubInterface* newVal);
    	END_INTERFACE_PART(LocalClass)
    };
    
    ---- MeinInterface.h ENDE ----
    
    ---- MeinTestClient.cs ----
    
    MeinInterface inter = new MeinInterface();
    inter.MeinSubinterface = new MeinSubinterface();
    inter.MeinSubinterface.Wert = "Bla";
    
    ---- MeinTestClient.cs ENDE ----
    

  • Mod

    1. Würde ich Dir dringend raten mit Smart-Zeigern zu arbeiten. Ich bevorzuge ATL CComPtr.
    2. put_MeinSubinterface muss in jedem Fall auf den alten Interface Zeiger ein Release machen.
    3. get_MeinSubinterface muss in jedem Fall ein AddRef machen. Denn der Nutzer ist verpflichet ein Release auf den Zeiger zu machen, den Du ihmn zurückgibst
    4. Du behandelst den Fall nicht, dass m_meinSubInterface NULL sein kann!



  • Vielen Dank für die Antwort. Ich werde mir mal angucken, was es mit den CComPtr auf sich hat. Also Punkt 2-4 würde ich dann so machen? vom eigentlichen Gedanken her ist alles richtig?

    IMeinSubInterface* CMeinInterface::get_MeinSubinterface(void)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());
        if(m_meinSubInterface != NULL) m_meinSubInterface->AddRef();
        return m_meinSubInterface;
    }
    
    void CMeinInterface::put_MeinSubinterface(IMeinSubInterface* newVal)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());
        if(m_meinSubInterface != NULL) m_meinSubInterface->Release();
        m_meinSubInterface = newVal;
        if(m_meinSubInterface != NULL) m_meinSubInterface->AddRef();
    }
    

  • Mod

    Du hast im Destruktor noch einen Release drin gehabt bei dem Du nicht auf NULL Zeiger prüfst.



  • Ich hab es nun in sofern umgebaut, dass ich nun im Header ein

    CComPtr<IMeinSubInterface> m_meinSubInterface;

    und alle AddRef() und Releases() gekillt habe. Leider kommt es immernoch zu abstürzen wenn ich das Feld "Wert" befüllen will, da beim Interface mittlerweile wieder released wurde. 😞


Anmelden zum Antworten