Creating an extension with COM
The complete source and makefiles are located in the XMLFoundation Examples/c++/ExATLCOM directory
Create a basic ATL COM project with Visual Studio
The following code sample is the standard app wizard written implementation header file
with a few small additions (Highlighted in red) required for XML support.
class ATL_NO_VTABLE CMyATLObj :
public CComCoClass<CMyATLObj, &CLSID_MyATLObj>,
public IDispatchImpl<IMyATLObj, &IID_IMyATLObj, &LIBID_EXATLCOMLib> ,
In your implementation file you’ll need to add the macro at a global scope
and implement MapXMLTagsToMembers() to define the Object to XML mappings.
This example maps an integer, a string, and a list of COM objects.
MapMember(&m_strString, “CustomerName”, &gGenericStrHandler);
MapMember(&m_lstCMyATLObj, CMyATLObj::GetStaticTag(), &gGListHandler,0);
In the ExATLCOM sample application several additional methods have been added to the COM Object. Most notably put_XMLState() that has the ability to assign members variables and create COM objects when supplied well-formed XML as input.
This example specifies a unique object ID composed of element/member data in the object. When an Object ID is specified put_XMLState() can then update COM object instances with new or more information. A common usage of this feature is to “drill down” on a list of customers, adding more data detail to one of the customer object instances. So for example given a customer that maps the attribute OID as the ObjectID:
The application may want more information on this customer. More information is retrieved (generally from the DBMS) and it may look like this:
The new information does not create a new XML state object and a new COM interface object, rather it updates the existing state object and uses the same COM Interface object. If however the oid of the new information was 2, then a new XML state object and a new COM interface would be created.
Visual Basic is the easiest way to demonstrate the functionality of this COM Object
From the “Project” menu add a “Reference”
Dim MyO As IMyATLObj
Then assign it in fromLoad() like this:
Set MyO = New MyATLObj
The application looks like this:
Buttons 1, 3, and 7 are all the same. They get the state of the COM object in XML representation and display it in the large text box to the right. The VB code to do that looks like this:
Text2 = MyO.XMLState
and that calls a method in the COM object in C++ that looks like this:
STDMETHODIMP CMyATLObj::get_XMLState(BSTR *pVal)
CComBSTR temp( ToXML() );
*pVal = temp.Copy();
Button 2 directly modifies the COM object through Native COM accessors like this:
MyO.TheCount = 777
MyO.TheString = “Hello World”
they call into the COM object and execute the standard ATL member accessors like this:
STDMETHODIMP CMyATLObj::put_TheString(BSTR newVal)
m_strString = (const char *)b;
Button 3, like Button 1 shows the XML state.
Button 4 makes no COM call. It only modifies the VB edit control to contain the following XML:
Button 5 takes the current value from the large edit control and stuffs it into the COM object. If you use the value in the edit control by button 4, then the base object 777 will be modified and two new objects (and their interfaces) will be created (123 and 456). The VB code looks like this:
MyO.XMLState = Text2
the ATL objects C++ code looks like this:
STDMETHODIMP CMyATLObj::put_XMLState(BSTR newVal)
FromXML((const char *)b);
Button 6 clears the large text box. VB code loos like this:
Text2 = “”
Button 7 displays the current state of the COM object in XML like buttons 1 & 3.
Button 8 retrieves a COM interface to one of the sub-objects (123 or 456) then displays the XML state of that object in a message box. The VB code looks like this:
Dim MyO2 As IMyATLObj
Set MyO2 = MyO.GetMyInterface(txtCustID.Text)
If (MyO2 Is Nothing) Then
MsgBox (“Requested CustomerID Not found”)
‘ invoke a method on the interface returned by GetMyInterface()
Set MyO2 = Nothing
The COM object has to search it’s list for the specified CustomerID then return the associated COM Interface for that object. The C++ code looks like this:
STDMETHODIMP CMyATLObj::GetMyInterface(long CustomerID, IUnknown **pIOResult)
XMLObject *pO = (XMLObject *)it++;
CComObject<CMyATLObj>*pIO = (CComObject<CMyATLObj>*)pO->GetInterfaceObject();
if (pIO->GetCustomerID() == CustomerID)
*pIOResult = pIO;
© 2015 United Business Technologies, Inc. All Rights Reserved.