From: Fred on

"Giovanni Dicanio" <giovanni.dicanio(a)invalid.it> wrote in message
news:%23GPzqfZIIHA.5360(a)TK2MSFTNGP03.phx.gbl...
>
> "Fred" <not(a)here.com> ha scritto nel messaggio
> news:Ko-dnZKGgvATpa_aRVnytAA(a)pipex.net...
>> Not directly MFC but I couldn't find an appropriate group.
>
> It's fine to ask here.
> However, you may find the ATL group:
>
> microsoft.public.vc.atl
>
> to be very interesting, too

Hi Giovanni,

Thanks for your comprehensive reply. As you may see my follow up crossed
your post and I realised my misunderstanding with Release().

I am curious though as to why some QueryInterface():Release() return 1 and
others 0.

I wonder why the Release after IBasicBitmapOps() returns 1?

How will IBasicBitmapOps() destroy inself if I don't do another literal
Release()? Is there an implicit one done for it when a "parent" Releases()?

But as long as I Release once after I have finished then I shouldn't have a
problem, correct?

Now, if I understand you right CoInitialize and CoUninitialize should be
called once per program.

Can/should I do the same with CoCreateInstance for each factory?

Say I will be manipulating many images throughout the life of my program.
Should I create just once instance of the factory at a high level and reuse
it (where possible)? All the code snippets I've seen (not many) call
CoCreateInstance as I did in my snippet - in the target function, once for
each object. But is that necessary? Is that for demonstration purposes or is
it best practise?

To be explicit could/should I use the one
pImageFactory->CreateBitmapFromImage() to create many bitmaps from many
iImages?

Regarding headers. How much overhead would adding ATL add?

My program is for windows CE and I want to keep it as tight as possible.

(Don't tell anyone here, but I'm trying to avoid using MFC too :) )

Cheers


>
>> As I understood it, you must release every resource obtained through
>> Queryinterface.
>> Would someone indicate why the pBasicBitmapOps->Release(); in the code
>> snippet below returns S_FALSE?
>> (the other Releases() return S_OK).
>
> Release is a method of IUnknown interface. IUnknown is the base interface
> for all COM objects. Every COM object must implement at least the IUnknown
> interface. IUnknown has three methods: QueryInterface, AddRef and Release.
> So, because every COM interface is derived from IUnknown, you can call
> QueryInterface, AddRef and Release on every COM interface.
>
> Note that the prototype of Release is as follow:
>
> "IUnknown::Release"
> http://msdn2.microsoft.com/en-us/library/ms682317.aspx
>
> ULONG Release(void);
>
> It is *not* "HRESULT Release(void)".
> So, you must not interpret the return value of Release as a flag
> indicating success or error (like S_OK, E_FAIL, etc. these are values
> valid only for variables of type HRESULT.)
>
> Release just returns the resulting value of the reference count of the
> object. This reference count value returned by Release is used for
> diagnostic/testing purposes only... you can just ignore it.
> (Instead, you must check every HRESULT returned value, e.g. from
> QueryInterface, or other interfaces methods.)
>
>
>> if (SUCCEEDED(pBitmapImage->QueryInterface(IID_IBasicBitmapOps,
>> (void**)&pBasicBitmapOps)))
>> {
>> hr=pBasicBitmapOps->Release();
>> }
>
> The above code is wrong.
> IUnknown::Release does not return HRESULT.
> Just call Release, like this:
>
> <code>
>
> // (Decreases object reference count;
> // when ref count becomes 0,
> // the object destroys itself.)
> pBasicBitmapOps->Release();
>
> // Avoid danging references
> pBasicBitmapOps = NULL;
>
> </code>
>
> Or better, use an ATL smart pointer template class, like CComPtr or
> CComQIPtr.
> These offer automatic management for AddRef and Release, and you don't
> have to pay attention to details like clearing pointer to NULL, to avoid
> dangling references. So, for example, when the smart pointer instance
> created on the stack goes out of scope, Release is automatically called by
> the smart pointer.
> These smart pointers help you write less code, less boilerplate, and more
> high-quality and more robust code. You can concentrate on the main
> algorithm, and don't pay attention to several details, and lose focus.
>
> e.g.
>
> CComPtr< IImageFactory > spImageFactory;
>
> // When you create with CoCreateInstance...
> hr = spImageFactory.CoCreateInstance( CLSID_ImagingFactory );
>
> (Release automatically called when you exit the function. [*] )
>
> See, for example, the CComPtr documentation on MSDN:
>
> "CComPtr Class"
> http://msdn2.microsoft.com/en-us/library/ezzw7k98(VS.80).aspx
>
> Giovanni
>
> [*] Note that, if you call CoInitialize and CoUninitialize in the same
> scope of the smart pointer, then in this particular case you have to force
> a Relase() call before calling CoUninitialize.
>
> e.g.
>
> // #1
> {
> CoInitialize...
>
> CComPtr< ISomething > spSomething;
>
> ...
> use spSomething
> ...
>
> // Call .Release() before CoUninitialize
> spSomething.Release();
> CoUninitialize...
> }
>
> // #2 - If CoInitialize/CoUninitialize are called in an higher context:
> {
> CComPtr< ISomething > spSomething;
>
> ...
> use spSomething
> ...
>
> // Don't need to call Release
> // spSomething.Release();
> }
>
> This is beacuse in case #1 the destructor of the smart pointer would be
> called after CoUninitialized, and so COM is already shut down, and then
> IUnknown::Release is called by the smart pointer destructor when COM is
> uninitialized, and strange bad things can happen.
> But, in general, I would call CoInitialize and CoUninitialize in a more
> higher context (case #2), like WinMain or _tmain(), etc. not in the same
> scope of the COM smart pointers.
>
>
>


From: Fred on

"Giovanni Dicanio" <giovanni.dicanio(a)invalid.it> wrote in message
news:%23cN99pZIIHA.6068(a)TK2MSFTNGP05.phx.gbl...
>
> "Fred" <not(a)here.com> ha scritto nel messaggio
> news:KPWdnTuv1IjX3q_anZ2dneKdnZydnZ2d(a)pipex.net...
>>
>> Note I see that it is not a Failure, it returns the value of the
>> reference
>> count, but I dont query IID_IBasicBitmapOps
>> anywhere else.
>
>>> if (SUCCEEDED(pBitmapImage->QueryInterface(IID_IBasicBitmapOps,
>>> (void**)&pBasicBitmapOps)))
>>> {
>>> hr=pBasicBitmapOps->Release();
>>> }
>
> What do you mean?
>
> You call QueryInterface for IID_IBasicBitmaoOps; so, on success,
> pBasicBitmapOps points to an IBasicBitmapOps interface.
> (Note that QueryInterface implementation calls AddRef.)
> Then you release the returned interface, calling Release.
>
> The error is to set the return value to "hr", beacuse Release does *not*
> return HRESULT.
>
> Other than that and not using smart pointers (which I suggest you to
> use...), your code seems correct.
>
> Giovanni
>

Yes, Thanks. See my other follow up where I wonder why the releasing the
interface doesn't return 0.


From: Giovanni Dicanio on

"Fred" <not(a)here.com> ha scritto nel messaggio
news:dbOdnYf-88rYxq_anZ2dnUVZ8qaqnZ2d(a)pipex.net...

> Thanks for your comprehensive reply.

You're welcome.


> I am curious though as to why some QueryInterface():Release() return 1 and
> others 0.
>
> I wonder why the Release after IBasicBitmapOps() returns 1?
> How will IBasicBitmapOps() destroy inself if I don't do another literal
> Release()? Is there an implicit one done for it when a "parent"
> Releases()?
>
> But as long as I Release once after I have finished then I shouldn't have
> a problem, correct?

Yes. It is correct.
You just call Release() when you are finished (and do yourself a favor :)
and clear the pointer to NULL, or better use a smart pointer like CComPtr).
If Release returns 1, it means that somewhere else someone else (e.g. the
parent or factory object) will release your interface.
If you follow COM rules about reference counting (and if the server object
implementer does this, too), there will be no memory or resource leak.


> Now, if I understand you right CoInitialize and CoUninitialize should be
> called once per program.

Yes. I don't know for the particular case of Windows CE, but it should work.
But please, do a test.


> Can/should I do the same with CoCreateInstance for each factory?

Are you speaking about IImagingFactory, right?
Well, it depends on the particular protocol of the interface...
For example, with DirectDraw, you can create the IDirectDrawN (N = version
number, e.g. IDirectDraw7) interface, which is a factory for DirectDraw
surfaces (IDirectDrawSurfaceN interface), only once in your program.
i.e. you create IDirectDraw once in your program, and call
IDirectDraw::CreateSurface method to create the children IDirectDrawSurface
interfaces. Then you release them, and finally you release main IDirectDraw
only once.
I don't know about the particular IImageFactory, but it may be the same.
Just do a test (computer science is an experimental science :)


> Regarding headers. How much overhead would adding ATL add?

It is about zero :)

In fact, ATL are just lean templates. Sometimes, you may see them as a kind
of advanced and robust evolution of C preprocessor macros...

I would suggest you to really use ATL in your context. At least, the robust
smart pointers for COM interfaces like CComPtr and CComQIPtr.
(Note that you can also use these ATL helper classes also in MFC.)


> My program is for windows CE and I want to keep it as tight as possible.
>
> (Don't tell anyone here, but I'm trying to avoid using MFC too :) )

I have no idea about embedded development.
So, in this context of embedded/mobile, is MFC too fat?
I believe that in normal Windows XP or Vista development, the overhead of
MFC over ATL or pure Win32 is acceptable, considering modern PCs big amount
of RAM and CPUs high speed...
However, ATL is very thin compared to MFC. For example, considering that ATL
is template based, you have no overhead for what you don't use; you just pay
for what you use. And you don't need external DLLs. And also, ATL wrappers
are very thin, e.g. ATL window wrapper is just a wrapper on HWND, while MFC
CWnd has more overhead.

This is a citation from a great tutorial on CodeProject:

WTL for MFC Programmers, Part I
ATL GUI Classes
===============================

http://www.codeproject.com/wtl/wtl4mfc1.asp

<cite>
CWindow is very different from MFC's CWnd. CWindow objects are inexpensive
to create, since there is only one data member, and there is no equivalent
to the object maps that MFC keeps internally to map HWNDs to CWnd objects.
Also unlike CWnd, when a CWindow object goes out of scope, the associated
window is not destroyed. This means you don't have to remember to detach any
temp CWindow objects you might create.
</cite>

Again, you may consider also ask COM and ATL questions to the ATL newsgroup.

Giovanni



From: Stuart Redmann on
Fred wrote:

> Not directly MFC but I couldn't find an appropriate group.

[snipped COM related question as it has been solved in different posts already]

What about microsoft.public.platformsdk.com_ole?

Regards,
Stuart
From: Fred on

"Stuart Redmann" <DerTopper(a)web.de> wrote in message
news:fgurb7$9q0$1(a)news.dtag.de...
> Fred wrote:
>
>> Not directly MFC but I couldn't find an appropriate group.
>
> [snipped COM related question as it has been solved in different posts
> already]
>
> What about microsoft.public.platformsdk.com_ole?
>
> Regards,
> Stuart

Thanks, just had a look.

No one lives there :)