Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Where to put #import and CoInitialize()

100 views
Skip to first unread message

Ron Ayoub

unread,
Oct 20, 2001, 7:55:20 PM10/20/01
to
I think I've figured out that the best place to put #import directives is
StdAfx.h. Is there any drop back to this method?

Also, I have overload a basic dialog box OnInitDialog() function like this.
Sorry for the code but it is straightforward. Am I using the CoInitialize
and CoUnitialize functions correctly. These are stupid questions but I want
to make sure I'm not missing something performance related or related to
when the size of a project become larger and larger.


BOOL CDialogData::OnInitDialog()
{
CDialog::OnInitDialog();

::CoInitialize(NULL);{

//declare _com_ptr_t pointers
_ConnectionPtr pConnection;
_CommandPtr pCommand;
_RecordsetPtr pRecordset;

//set up connection
pConnection.CreateInstance(__uuidof(Connection));
pConnection->Open(
_bstr_t("Provider=sqloledb;Data Source=ayoubhome;Initial
Catalog=pubs;User Id=sa;Password=;"),
_bstr_t(""),
_bstr_t(""),
adModeUnknown);

//set up command
pCommand.CreateInstance(__uuidof(Command));
pCommand->ActiveConnection = pConnection;
pCommand->CommandText = "select * from authors order by au_lname";

//set up recordset
pRecordset.CreateInstance(__uuidof(Recordset));
pRecordset->CursorLocation = adUseClient;
pRecordset->Open( (IDispatch *) pCommand, vtMissing, adOpenStatic,
adLockBatchOptimistic, adCmdUnknown);

//get some data from the recordset
pRecordset->MoveFirst();
while (!pRecordset->GetadoEOF())
{
_bstr_t value(pRecordset->Fields->GetItem("au_fname")->Value.bstrVal);
m_cboAuthors.AddString((LPCTSTR)value);
pRecordset->MoveNext();
}

//close recordset and connection
pRecordset->Close();
pConnection->Close();

}::CoUninitialize();

return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}


Roy Fine

unread,
Oct 20, 2001, 9:34:05 PM10/20/01
to
Ron,

putting the #import directive in stdafx.h is the right thing to do (in my
opinion) - you generate the tlh/tli header files only once. compile
performance is substantially improved...

I would put ::CoInitialize in a constructor and ::CoUninitialize in a
destructor - like the CWinApp derived class in an SDI app. Optionally, I
would place the CoInitialize in the InitInstance as in your example, but I
would place the CoUninitialize call in ExitInstance. You have correctly
placed brackets around the code segment to force the smart pointers to go
out of scope before the CoUninitialize call (and corrected the memory access
violations) - but I would argue that such is not maintenance friendly unless
it is accompanied by loads of comments. My tendency is to write code that
does not need a lot of comments to explain or warn of caveats, and other
dangerous happenings. But that is purely a style issue. You code looks OK.

best reagards
roy fine


p.s. : open your recordset read only (adLockReadOnly) if you are just
populating a control. With your client-side cursor, that will place fewer
demands on the network and client computer resources.

roy


"Ron Ayoub" <rona...@hotmail.com> wrote in message
news:I9oA7.5640$J12.6...@newsread1.prod.itd.earthlink.net...


> I think I've figured out that the best place to put #import directives is
> StdAfx.h. Is there any drop back to this method?
>
> Also, I have overload a basic dialog box OnInitDialog() function like
this.
> Sorry for the code but it is straightforward. Am I using the CoInitialize
> and CoUnitialize functions correctly. These are stupid questions but I
want
> to make sure I'm not missing something performance related or related to
> when the size of a project become larger and larger.
>
>
> BOOL CDialogData::OnInitDialog()
> {
> CDialog::OnInitDialog();
>
> ::CoInitialize(NULL);{
>

> file://declare _com_ptr_t pointers


> _ConnectionPtr pConnection;
> _CommandPtr pCommand;
> _RecordsetPtr pRecordset;
>

> file://set up connection


> pConnection.CreateInstance(__uuidof(Connection));
> pConnection->Open(
> _bstr_t("Provider=sqloledb;Data Source=ayoubhome;Initial
> Catalog=pubs;User Id=sa;Password=;"),
> _bstr_t(""),
> _bstr_t(""),
> adModeUnknown);
>

> file://set up command


> pCommand.CreateInstance(__uuidof(Command));
> pCommand->ActiveConnection = pConnection;
> pCommand->CommandText = "select * from authors order by au_lname";
>

> file://set up recordset


> pRecordset.CreateInstance(__uuidof(Recordset));
> pRecordset->CursorLocation = adUseClient;
> pRecordset->Open( (IDispatch *) pCommand, vtMissing, adOpenStatic,
> adLockBatchOptimistic, adCmdUnknown);
>

> file://get some data from the recordset


> pRecordset->MoveFirst();
> while (!pRecordset->GetadoEOF())
> {
> _bstr_t value(pRecordset->Fields->GetItem("au_fname")->Value.bstrVal);
> m_cboAuthors.AddString((LPCTSTR)value);
> pRecordset->MoveNext();
> }
>

> file://close recordset and connection

Doug Harrison [MVP]

unread,
Oct 21, 2001, 6:33:07 PM10/21/01
to
Roy Fine wrote:

>I would put ::CoInitialize in a constructor and ::CoUninitialize in a
>destructor - like the CWinApp derived class in an SDI app. Optionally, I
>would place the CoInitialize in the InitInstance as in your example, but I
>would place the CoUninitialize call in ExitInstance.

That's the right idea, but the best way I know to do it is to write a
ComInitializer class, whose ctor initializes COM and whose dtor
uninitializes it. This makes it easy to write a function which uses
COM, and if your entire app is to use COM, make it a member variable
of your CWinApp class. (However, in MFC apps, I typically just call
AfxOleInit() in my InitInstance.)

In general, whenever you have a resource which you explicitly acquire
and release, you need a dedicated class to manage it. If you don't
have such a class, and you acquire the resource in some other ctor,
and that ctor subsequently throws an exception, the complementary dtor
isn't called, and you have a resource leak. (Similarly for
Init/ExitInstance.) But if your resource is owned by an object of a
class such as ComInitializer, its successful construction as a member
variable or local variable ensures that the compiler will call its
dtor, however it goes out of scope, thus guaranteeing the release of
the resource.

>You have correctly
>placed brackets around the code segment to force the smart pointers to go
>out of scope before the CoUninitialize call (and corrected the memory access
>violations) - but I would argue that such is not maintenance friendly unless
>it is accompanied by loads of comments.

By using ComInitalizer, the OP can lose those brackets, which don't
make the function entirely exception-safe anyway, because if his code
throws an exception, CoUninitialize() will never be called.
ComInitializer addresses both problems.

--
Doug Harrison [VC++ MVP]
Eluent Software, LLC
http://www.eluent.com
Tools for Visual C++ and Windows

Roy Fine

unread,
Oct 21, 2001, 11:44:24 PM10/21/01
to

"Doug Harrison [MVP]" <d...@mvps.org> wrote in message
news:eti6ttcoeimjsbnta...@4ax.com...

> Roy Fine wrote:
>
>
> That's the right idea, but the best way I know to do it is to write a
> ComInitializer class, whose ctor initializes COM and whose dtor
> uninitializes it. This makes it easy to write a function which uses
> COM, and if your entire app is to use COM, make it a member variable
> of your CWinApp class.

I was using the CWinApp derived class as such. The separate class is a nice
touch, especially when the entire app is not COM enabled.

> (However, in MFC apps, I typically just call
> AfxOleInit() in my InitInstance.)
>

Exactly, but I was proactively avoiding the chastisement for not releasing
all acquired resources.

The biggest problem that I have seen with introductiory COM users is 1) not
calling CoInitialize, and 2) calling CoUninitialize with smart pointers
still on the stack...

thanks,
roy fine

0 new messages