2011-08-18 2 views
3

J'héberge un contrôle IWebBrowser2 dans mon programme C++ en utilisant simplement Win32 (pas de mfc, atl, wtl etc.). Sur DISPID_NAVIGATECOMPLETE2, j'ajoute un objet personnalisé accessible à partir de javascript exécuté sur la page Web affichée.Pourquoi toutes les références à mon objet IDispatch ne sont-elles pas publiées?

Pour ajouter l'objet personnalisé, j'appelle InvokeEx avec DISPATCH_PROPERTYPUT et une structure DISPPARAMS avec un pointeur vers mon objet personnalisé.

Pendant l'appel à InvokeEx, la fonction AddRef de mon objet personnalisé est appelée et j'incrémente son compteur de référence. Mais l'objet ne reçoit jamais d'appel à sa fonction Release, de sorte que le compteur de référence ne redescend jamais à zéro.

Qui est responsable de l'appel de Release() après l'appel de AddRef() dans InvokeEx?

EDIT: (Ajout d'un code)

Ceci est le code qui ajoute mon objet personnalisé à la IHTMLWindow2. custObj des points à mon objet personnalisé

IHTMLWindow2 *win = NULL; 
GetDoc()->get_parentWindow(&win); 
IDispatchEx *winEx = NULL; 
win->QueryInterface(&winEx); 

DISPID dispid; 
HRESULT hr = winEx->GetDispID(objName, fdexNameEnsure, &dispid); //objName is "JSObject" 

DISPID namedArgs[] = {DISPID_PROPERTYPUT}; 
DISPPARAMS params; 
params.rgvarg = new VARIANT[1]; 
params.rgvarg[0].pdispVal = custObj; 
params.rgvarg[0].vt = VT_DISPATCH; 
params.rgdispidNamedArgs = namedArgs; 
params.cArgs = 1; 
params.cNamedArgs = 1; 

hr = winEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL); 

Ceci est l'objet que j'ajoute (certains députés ont été omis par souci de concision)

class JSObject : public IDispatch { 
private: 
    long ref; 
public: 
    JSObject(); 

    // IUnknown 
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv); 
    virtual ULONG STDMETHODCALLTYPE AddRef(); 
    virtual ULONG STDMETHODCALLTYPE Release(); 

    // IDispatch 
    virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo); 
    virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, 
     ITypeInfo **ppTInfo); 
    virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, 
     LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId); 
    virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, 
     LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, 
     EXCEPINFO *pExcepInfo, UINT *puArgErr); 
}; 

EDIT 2:

maintenant qu'il semble fonctionner comme si je devais décider de le mettre sur github.

https://github.com/Tobbe/CppIEEmbed. S'il vous plaît fourchez et améliorez si vous pouvez :)

+0

Indiquez exactement la propriété que vous affectez. Cela devrait être DISPATCH_PROPERTYPUTREF btw puisque vous assignez un objet. –

+0

Si j'utilise DISPATCH_PROPERTYPUTREF InvokeEx échoue avec DISP_E_MEMBERNOTFOUND – Tobbe

+0

@Hans Passant: Je ne suis pas tout à fait sûr de ce que vous demandez lorsque vous dites "Document exactement quelle propriété vous affectez". Est-ce que le code que j'ai ajouté à ma question vous donne ce que vous avez demandé? – Tobbe

Répondre

2

Eh bien, vous attribuez une propriété, n'est-ce pas? Tant que cette propriété existe et fait référence à votre objet, une référence sera ajoutée.

Si vous souhaitez que l'objet distant libère votre référence, vous devez affecter la valeur NULL à la propriété ou à un autre objet.

+0

J'aurais dû le préciser dans ma question, mais le fait est que ma référence n'est pas libérée même lorsque "l'objet distant" est détruit. Ne devrait-il pas libérer toutes ses propriétés assignées avant de mourir? – Tobbe

+0

Je devrais. Mais es-tu sûr que l'objet distant est vraiment détruit, et qu'il n'y a pas d'autres références qui pendent? – rodrigo

+0

Je ne libérais pas correctement l'objet distant, donc il n'a jamais été détruit. Et comme il n'a jamais été détruit, il a gardé sa référence à mon objet personnalisé (mon instance JSObject). – Tobbe

Questions connexes