----- Original Message ----- From: "Mike Hearn" mike@theoretic.com To: wine-devel@winehq.com Sent: Monday, June 16, 2003 3:16 PM Subject: Re: TypeLib containment refcounting
On Mon, 16 Jun 2003 14:43:25 -0500, Sir Kelly Leahy scribed thus:
I would expect you to addref the typelib when the ITypeInfo pointer is created, and then when it is destroyed to release it.
I believe that's what I'm doing. Maybe not.
I think what is actually going on, is that this method returns a pointer to an internal interface that's always present. There is no construction as such. From MSDN:
HRESULT GetTypeInfoOfGuid( REFGUID guid, ITypeInfo FAR* FAR* ppTinfo ); Retrieves the type description that corresponds to the specified GUID.
This confuses me. Does the caller need to release the interface? The page doesn't mention refcounting at all.
"Retrieves" is somewhat fuzzy. The fact that it's a pointer to a pointer suggests that maybe you get a pointer to an internal interface and you shouldn't do any refcounting on it.
The caller should release the object when they're done with it. I guess what I was saying is that there's a few ways this can be done.
One way is for ITypeInfo_AddRef() to addref the type library object that contains it (i.e. add one to the refcount on the ITypeLib struct in C terms). It can either do this every time (in which case, ITypeInfo_Release() should release the type library object each time) or it can do it only when the refcount is zero on entry to ITypeInfo_AddRef() (in which case ITypeInfo_Release() should only Release() the type library object when the result of decrementing the refcount is zero in ITypeInfo_Release()).
Another way is the addref the type library when the ITypeInfo wherever a ITypeInfo interface is initially created (like in GetTypeInfoOfGuid) but I think this is more dangerous, since then you have to have some way for this refcount to go away, and ITypeInfo_Release() doesn't know who created it, just that it was created. If you are careful enough to always put an addref on the library when you create a new ITypeInfo pointer (GetTypeInfoOfGuid, GetTypeInfo, IDispatch::GetTypeInfo, etc.) but this seems like a unwieldy task to guarantee that the code is right in all of these places. It's much easier to make the ITypeInfo_AddRef() and ITypeInfo_Release() call ITypeLib_AddRef() and ITypeLib_Release() on the containing ITypeLib implementation when appropriate.
In the object that implements the ITypeInfo reference, you should have a pTypeLib->Release() in the destructor and a pTypeLib->AddRef() somewhere
in
the code that creates the ITypeInfo implementing object.
Well that's C++ stuff. Remember that all this is implemented in pure C. The relevant code searches a linked list for a ITypeInfoImpl struct, which stores all the data and the COM Vtable. It then casts it to an ITypeInfo and incs the refcount:
*ppTInfo = (ITypeInfo*)pTypeInfo; ITypeInfo_AddRef(*ppTInfo);
So, what you actually get out of this method is a pointer to an internal data structure rather than a constructed object....
Sorry... I didn't have the source handy to look at (RMAing my linux box HDD right now!)
As far as C++ stuff vs. C stuff, in essence the pointer to the data structure (including the VMT) is simply a C++ style class without the C++, and with some special requirements... You can just replace my p->method() with OBJECT_method(p) if you like to make it look like what I've seen from wine. I'm still pretty new to the wine source, so it may not be like this everywhere, I just don't have the time to look.
Kelly