.NET Forum / Languages / Managed C++ / May 2005
Good tutorial for learning usage of COM from VC++?
|
|
Thread rating:  |
Burt Johnson - 27 Apr 2005 06:47 GMT I have to use a COM DLL written by another person, and am having trouble. Part of the problem is that I am writing inside another DLL (non-COM), and do not know what has been CoInitialized or CoCreated yet by the calling program.
Is there an Online tutorial somewhere that you could recommend for me to learn how to handle situations like this? I am a complete newbie to COM, so I would need something that isn't too super-advanced.
In my current version I do the following:
CoInitialize(NULL); HResult hr = CoCreateInstance ();
<stuff>
if (SUCCEEDED(hr)) CoUnitialize();
I have tried it both with that last unitiailze and without and get the same results. On quitting my test program, in 2 of my 10 tests, the program hangs. When I do a "break all" it tells me that the program is locked. I always find it at the destructor for ComPtr.
Any direct hints, or pointers to tutorials that will help are appreciated! I haven't found much of use in MSDN, which surprised me.
 Signature - Burt Johnson MindStorm, Inc. http://www.mindstorm-inc.com/software.html
Bonj - 27 Apr 2005 08:27 GMT You need to call CoInitialize(), as the consumer of the COM object. Whether the object itself does depends on whether it consumes any other COM object, but that doesn't matter as it's a black box to you. Make sure you let all COM objects go out of scope (if they're smart pointers) or call Release() on them if not, *before* CoUninitalize() is called.
>I have to use a COM DLL written by another person, and am having > trouble. Part of the problem is that I am writing inside another DLL [quoted text clipped - 22 lines] > Any direct hints, or pointers to tutorials that will help are > appreciated! I haven't found much of use in MSDN, which surprised me. Burt - 28 Apr 2005 01:40 GMT Thanks! that got me moving in the right direction.
The problem was that I had a "smart pointer" as a class variable in the same class that was doing the CoUninitialize. Thus, it was going out of scope too late -- after the uninitalize.
The solution was to make it a method-local variable, and change my logic slight to accommodate that. Once I made that change, everything started working as desired. :-)
> You need to call CoInitialize(), as the consumer of the COM object. > Whether the object itself does depends on whether it consumes any other > COM object, but that doesn't matter as it's a black box to you. > Make sure you let all COM objects go out of scope (if they're smart > pointers) or call Release() on them if not, *before* CoUninitalize() is > called. Bonj - 30 Apr 2005 16:00 GMT Yes, you can have something like void mymethod(....params...) { CoInitialize(NULL); { _MySmartPtr mycomobject; ... mycomobject->DoMethods() ... } //mycomobject goes out of scope here CoUninitialize(); } to keep it in one method. The inner curly brackets create a nested level of scope.
technically you probably could also use void mymethod(....params...) { CoInitialize(NULL); _MySmartPtr mycomobject; ... mycomobject->DoMethods() ... mycomobject.Release(); CoUninitialize(); }
but the former is definitely the better syntax. Also if this method is in a worker thread remember to call OleInitialize(NULL), rather than CoInitialize(NULL).
> Thanks! that got me moving in the right direction. > [quoted text clipped - 12 lines] >> pointers) or call Release() on them if not, *before* CoUninitalize() is >> called. Jerry Coffin - 30 Apr 2005 17:33 GMT > Yes, you can have something like > void mymethod(....params...) [quoted text clipped - 10 lines] > to keep it in one method. The inner curly brackets create a nested level of > scope. Better yet:
struct UseCom { ComUser() { CoInitialize(NULL); }
~ComUser() { CoUnitialize(); } };
void mymethod() { UseCom c;
SmartPtr ComObject; // ... ComObject->DoMethods(); }
Note that you don't actually DO anything with the UseCom object -- simply by defining it, COM gets initialized when you enter the scope, and uninitialized when you leave it.
Also note that any identifier starting with an underscore followed by a capital letter (e.g. _MySmartPtr above) is reserved for the implementation -- i.e. you shouldn't define anything with a name like that.
 Signature Later, Jerry.
The universe is a figment of its own imagination.
Jerry Coffin - 30 Apr 2005 17:46 GMT [ ... ]
> struct UseCom { > ComUser() { [quoted text clipped - 5 lines] > } > }; Oops -- those should be UseCom and ~UseCom respectively, of course.
 Signature Later, Jerry.
The universe is a figment of its own imagination.
Burt Johnson - 30 Apr 2005 19:20 GMT That is very close to what I ended up doing. Thanks for all the suggestions!
A coworker noted that I could not use Release() on a smart pointer, but that I could do "ptr = NULL" in the destructor, which would accomplish the same thing. I had already changed the logic by that time, but I will keep this in mind next time too.
> Better yet: > [quoted text clipped - 24 lines] > implementation -- i.e. you shouldn't define anything with a name like > that.
 Signature - Burt Johnson MindStorm, Inc. http://www.mindstorm-inc.com/software.html
Bonj - 01 May 2005 23:45 GMT That's probably *as good*, but I'm not sure about better... when you write UseCom c; SmartPtr ComObject; you're relying on c going out of scope before ComObject, just because it was created first. If this is in the C++ standard then it's just as good, but even so it's not as clear if you don't know whether that is in the standard. With the method I posted, there's no ambiguity.
>> Yes, you can have something like >> void mymethod(....params...) [quoted text clipped - 40 lines] > implementation -- i.e. you shouldn't define anything with a name like > that. Jerry Coffin - 02 May 2005 03:46 GMT > That's probably *as good*, but I'm not sure about better... when you write > UseCom c; > SmartPtr ComObject; > you're relying on c going out of scope before ComObject, just because it was > created first. If this is in the C++ standard then it's just as good, but > even so it's not as clear if you don't know whether that is in the standard. First of all, it is required by the standard -- construction happens in the order the objects are defined, and destruction is a mirror image, happening in reverse order of construction.
Second, it has some real advantages. The primary one is exception safety. If an exception is thrown somewhere in the middle of the code, the rest of the code in that scope will not be executed, so (for example) your code to clean up COM, would get skipped over and never executed.
The compiler DOES know one thing though: when a scope is being exited all objects that have been created local to that scope must be destructed -- and this holds whether it exits normally OR via an exception.
Exception-safe code typically starts to take a form in which resources are acquired only in ctors and released in the matching dtors. This makes it easy to assure that the resources are released properly even when exceptions get thrown. This practice is common enough that it has its own acronym: RAII (Resource Acquisition Is Initialization).
> With the method I posted, there's no ambiguity. There's no ambiguity either way. The fact that you don't _know_ what the standard says doesn't mean it's ambiguous. :-)
 Signature Later, Jerry.
The universe is a figment of its own imagination.
Malcolm Clarke - 30 Apr 2005 17:18 GMT Try http://www.vanwijk.com/
They have some excellent online books. including Activex Programming With Visual C++
> I have to use a COM DLL written by another person, and am having > trouble. Part of the problem is that I am writing inside another DLL [quoted text clipped - 22 lines] > Any direct hints, or pointers to tutorials that will help are > appreciated! I haven't found much of use in MSDN, which surprised me. Burt Johnson - 30 Apr 2005 19:17 GMT > www.vanwijk.com Thanks for the pointer. I see ActiveX, but not COM there. Are the two really the same from a programming view? I have certainly heard of ActiveX, but never seen it from a programmatic side.
 Signature - Burt Johnson MindStorm, Inc. http://www.mindstorm-inc.com/software.html
Malcolm Clarke - 01 May 2005 21:32 GMT I thought they were one and the same. If I am wrong can somebody point out the difference.
Chapter 12 covers ActiveX COM Objects
> > www.vanwijk.com > > Thanks for the pointer. I see ActiveX, but not COM there. Are the two > really the same from a programming view? I have certainly heard of > ActiveX, but never seen it from a programmatic side. Jerry Coffin - 01 May 2005 22:21 GMT [ ... ActiveX and COM ]
> I thought they were one and the same. If I am wrong can somebody point out > the difference. They're close by not quite the same. COM is a protocol -- a specification for how two things can talk to each other. ActiveX is a specification for how a control works, which happens to depend on the COM protocol. COM could/can be used by things other than ActiveX though. It was originally designed for embedding documents via OLE, and it still works fine for that as well. Realistically, the difference between the two is rather blurry at best though...
 Signature Later, Jerry.
The universe is a figment of its own imagination.
Burt Johnson - 01 May 2005 23:41 GMT > [ ... ActiveX and COM ] > [quoted text clipped - 8 lines] > and it still works fine for that as well. Realistically, the > difference between the two is rather blurry at best though... Thanks for that explanation. I had seen both terms, but did not really know the boundary between them.
 Signature - Burt Johnson MindStorm, Inc. http://www.mindstorm-inc.com/software.html
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|