为什么对我的 IDispatch 对象的所有引用都没有被释放?
我在我的 C++ 程序中托管一个 IWebBrowser2 控件,只使用普通的 Win32(没有 mfc、atl、wtl 等)。在 DISPID_NAVIGATECOMPLETE2 上,我添加了一个自定义对象,可以从显示网页上运行的 javascript 访问该对象。
为了添加自定义对象,我使用 DISPATCH_PROPERTYPUT 和带有指向自定义对象的指针的 DISPPARAMS 结构调用 InvokeEx。
在调用 InvokeEx 期间,将调用自定义对象的 AddRef 函数,并增加其引用计数器。但该对象永远不会调用其 Release 函数,因此引用计数器永远不会再次减少到零。
在 InvokeEx 中调用 AddRef() 后,谁负责调用 Release() ?
编辑:(添加一些代码)
这是将我的自定义对象添加到 IHTMLWindow2 的代码。 custObj
指向我的自定义对象
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, ¶ms, NULL, NULL, NULL);
这是我要添加的对象(为简洁起见,省略了一些私有成员)
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);
};
编辑2:
现在它似乎正在工作就像我应该决定把它放在 github 上一样。
https://github.com/Tobbe/CppIEEmbed。如果可以的话,请分叉并改进:)
I'm hosting an IWebBrowser2 control in my C++ program using nothing but plain Win32 (no mfc, atl, wtl etc). On DISPID_NAVIGATECOMPLETE2 I add a custom object to be accessed from javascript running on the displayed webpage.
To add the custom object I call InvokeEx with DISPATCH_PROPERTYPUT and a DISPPARAMS structure with a pointer to my custom object.
During the call to InvokeEx the AddRef function of my custom object is called and I increment its reference counter. But the object never gets a call to its Release function, so the reference counter never decreases down to zero again.
Who is responsible for calling Release() after AddRef() has been called in InvokeEx?
EDIT: (Adding some code)
This is the code that adds my custom object to the IHTMLWindow2. custObj
points to my custom object
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, ¶ms, NULL, NULL, NULL);
This is the object that I'm adding (some private members have been left out for brevity)
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:
Now that it seems to be working like it should I decided to put it on github.
https://github.com/Tobbe/CppIEEmbed. Please fork and improve if you can :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,你正在分配财产,不是吗?只要此属性存在并引用您的对象,就会添加一个引用。
如果您希望远程对象释放您的引用,您应该将 NULL 分配给属性或其他对象。
Well, you are assigning a property, aren't you? As long as this property exists and refers to your object, it will have a reference added.
If you want the remote object to release your reference you should assign NULL to the property, or some other object.