COM Objects and C++

alocurto

Platinum Member
Nov 4, 1999
2,174
0
76
I need to do some research on C++ and external COM objects. Can anyone provide a rough overview? I am extremely familiar with C++ but just wanted to clarify what exactly a COM object is and how do I use them. Any links would be great. I used google to search for COM object stuff but did not find anything that helped me understand what exactly they are. Any feedback would be great. Thanks!
 

bot2600

Platinum Member
May 18, 2001
2,075
0
76
a COM object is basically an instatiation of a class that is external to your code. same black box use as a class, methods and properties and is accessed through an interface which is a vtable of pointers to the methods/properties in the class(es) in the COM object. My definition is very short, but HUGE books are written on the subject:eek:
 

alocurto

Platinum Member
Nov 4, 1999
2,174
0
76
Well, believe it or not, that helps immensly. I just needed a brief overview of how these two things related to one another. I am assuming that the COM objects provide functionality above and beyond the capabilities of C++ but can be called from C++ and return data. Is that a correct assumption? Anyone got a link of COM objects and some sample code?
 

glugglug

Diamond Member
Jun 9, 2002
5,340
1
81
COM is a "language independent" way to expose object functionality.

Language independent in the sense it can be called from anything. But not truly independent because all the standard data types in it are centered around bass ackwards VB. Half of the headaches arise from fubar VB internal data structures.

The #1 reason you would make a COM object rather than just a normal DLL is to be able to call everything easily from VB & ASP.

 

glugglug

Diamond Member
Jun 9, 2002
5,340
1
81
Important concept to keep in mind while learning COM, especially if you use MTS/COM+ as an RPC mechanism:

COM is centered around interfaces meaning exposed functions, not data. Technically your COM DLLs are supposed to be "stateless," meaning one function call should not set any internal variables that affect the next call unless they are called through the same object. (Keyword there is object not class).

The closest thing to a public data element rather than a method call is a "property" which is actually implemented as a pair of functions, one to set the piece of data and one to retrieve it.

If you are writing COM components in C++ you will most likely be using the ATL template libraries which get most of the dirty work done, but are extremely confusing to look at as they are composed ENTIRELY of #define macros and template classes. The wizards built into VC++ will create skeleton code using those template libraries for you.
 

Descartes

Lifer
Oct 10, 1999
13,968
2
0
Language independent in the sense it can be called from anything. But not truly independent because all the standard data types in it are centered around bass ackwards VB. Half of the headaches arise from fubar VB internal data structures.

Yes, it can be called from anything that has vtable/early/late binding facilities for COM components. "Standard" data types? COM doesn't define any data types. The types are defined in IDL *independent* of the implementation language. VB's data types are not "bass ackwards." The typelib emitted from a VB COM component are mapped to the appropriate type of the consuming language (C++ _bstr_t for VB String, C++ int for VB Long, etc.).

The #1 reason you would make a COM object rather than just a normal DLL is to be able to call everything easily from VB & ASP.

There are a thousand more reasons, all of which I can't permute. The core idea behind COM was to decouple the interface from implementation. If you're doing a LoadLibrary() on a native DLL, you're hardly decoupling yourself from implementation. The old programming mantra applies: program to an interface, not an implementation.

COM is centered around interfaces meaning exposed functions, not data.

You're talking encapsulation, not interfaces. Interfaces expose a contract only, no implementation. Every library, whether native DLL or COM component, exposes functions.

Technically your COM DLLs are supposed to be "stateless," meaning one function call should not set any internal variables that affect the next call unless they are called through the same object. (Keyword there is object not class).

I know you scoped the convo to MTS/COM+, but COM components don't need to be inherently stateless, even in the context of MTS/COM+. Many components serialize their state to a property bag or some other means to persist state even though they're technically stateless in the context of MTS/COM+ (i.e. they SetComplete/SetAbort each time).
 

glugglug

Diamond Member
Jun 9, 2002
5,340
1
81
"Standard" data types? COM doesn't define any data types. The types are defined in IDL *independent* of the implementation language. VB's data types are not "bass ackwards." The typelib emitted from a VB COM component are mapped to the appropriate type of the consuming language (C++ _bstr_t for VB String, C++ int for VB Long, etc.).

The atomic datatypes (int, long, float, etc) are universal to pretty much every language rather than VB specific.
But if you want to send/receive more complex datatypes such as arrays and even strings, then the types are molded to VB. (Yes, for an in-process DLL the types can be whatever you want, but if you want COM to know how to marshall your params outside the process....)

Getting other languages to use the VB string format (BSTR) is the source of lots of programming bugs. Some genious decided it would be a good idea to pass this datatype as a pointer to the spot in memory 2 bytes after the start of the block allocated for it, rather than as a pointer to the start of the block like everything else. Because of this if you try to create a BSTR in memory and allocate it with normal memory allocation routines like AllocMem or malloc, you get unpredictable results (so they had to make separate memory management routines just for BSTRs).

The VARIANT format is also a major kludge, particularly when it comes to VARIANTs containing arrays. First of all, the order of array indices for multi-dimenstional arrays in VB (and consequently in variant SAFEARRAYs) is exactly opposite what it is with standard arrays in pretty much every other language. Second of all, when receiving variants containing arrays or objects, you can't depend on things to use them sanely and have the actual variant passed (for an array of ints for example) have type VT_ARRAY | VT_I4, or maybe VT_ARRAY | VT_VARIANT (if passed as an array of variants containing ints). Instead when receiving such a param built in the simplest way possible in VB or VBScript, it is more likely to be of type VT_VARIANT | VT_BYREF (variant containing reference pointer to a variant), and when you look at that inner variant it is likely to also be of type VT_VARIANT | VT_BYREF, so you have to set up a loop to find the actual innermost variant you wanted to get to the array. (With some versions of VBScript/ASP calling COM+ I've seen the receiving application have to loop up to 4 times, i.e. the variant param received is actually a variant containing a pointer to a variant containing a pointer containing a variant containing a pointer to a variant containing a pointer to a safearray).