Leveraging C++ Applications Using COM (An Extension of the Document View Architecture)

Implementation

Although the big picture view of COM technology is straightforward, the actual implementation is intimidating. In the big picture, COM lets a program (the client) safely run binary code in another executable or DLL (the COM server) on your computer or on any computer to which you are linked.  In practice this means that the client uses COM to ask a COM server for an interface to an object.  If the object supports this interface the server will return to the client a pointer to this interface. The client can then use this pointer to manipulate and exchange information with the object. If the server does not support the interface (or it could be returned for some other reason), then the return code will let you know.  What makes this special is that the language used to generate the server's binary code is irrelevant. COM takes care of all the details to ensure that the execution and exchange of data between the client code and the COM server is handled correctly. [3]

The intimidating part of COM is making sure all these details get handled correctly.  Among the details involved include: 1) making sure the client code can locate the COM object to use, 2) ensuring that the client code and the COM object can share information, and 3) making sure that resources used to create the COM object are managed correctly. These items have associated with them legions of new acronyms, data types, and methods. The most important thing to do while learning these new acronyms, data types, and methods is to keep yourself from running from the room screaming. We recommend the books listed below which will help you get up and running with COM.

Fortunately, MFC and ATL have created Wizards, macros, templates, and other tools that automate most of the particularly inscrutable aspects of implementing a COM server or COM client. We have written two companion articles that describe the steps to convert an existing class in a monolithic C++ application into a COM server. Because we needed to access the COM server from an Active Server Page web site and from within Excel using VBA, we needed to provide an Automation interface rather than the more general custom interfaces. Clients such as VBA and VBScript only support automation interfaces and not custom interfaces. Automation uses the IDispatch interface and can only pass automation data such as VARIANTs and not, for example, abstract data types.  However, if you are trying to drive the server from VBA or VBScript, being limited to the basic data types (through VARIANT) is probably not a problem. (The server code itself is, free to use whatever data types it needs to use - the data type limitation is only on what can be passed back and forth to the client application.)

Example

The attached code and example is not from DBViewer but it illustrates the same concepts.  The sample demonstrates how COM technology can enhance well-designed applications using the document-view architecture.
    The attached zip file contains the following:
    1. Source code to build a COM server: ComSample.zip.
    2. Source code to build the View application: DlgView.zip.
    3. Source Code for the Document DLL: DocEngine2.zip.
    4. COMDEMO.xls.  An Excel 97 spreadsheet file.
    5. All the EXEs and DLLs if you simply want to run the code.  Please remember to register the ComSample.DLL.
To run the sample you will need to build the attached source code for the COM server, the view application, and the document DLL.

The View

The sample takes a very simple application that implements the document view architecture.  The view comprises of a single dialog based application that displays some text in a static control.  This application is dependent on a document  for what it will display but the application does not contain the document.  In this sample the document is provided by the DocEngine DLL using COM.

The Document

The DocEngine DLL has a single class called CSomethingComplicated.  CSomethingComplicated represents a complex class hierarchy of classes representing a document engine for a system.  The system's document engine is responsible for manipulating data, performing computations, and any other data related processes. However, in this sample CSomethingComplicated only has a single function HelloWorld() which returns "Hello World" as a CString (MFC).  The CSomethingComplicated class is exported from the DLL making it available to the user for use and allowing the user to derive new classes from it.

The COM Server

The COM server is a very simple class that inherits from CCmdTarget.  The COM server accesses the DocEngine DLL and provides an interface to the CSomethingComplicated.HelloWorld() function.  In a more realistic world, several COM classes could be built each representing some part of the DocEngine and providing an interface for it. The COM server makes the DocEngine available to other applications/systems such as ASP, MS Excel, Visual Basic etc.
Notice that converting the existing C++ code to be COM compatible was quite easy.

Conclusion

This article shows how easy it can be to a convert a typical monolithic MFC Document/View application into a COM Server.  However, this only scratches the surface for what COM can do. For example, the DBViewer application could be broken into a series of COM server chunks to provide even greater flexibility to client applications. Each of the C++ application's views can be turned into ActiveX Controls and used by both the C++ executable and the web server. The views could even be embedded into presentation software to allow clients (i.e., the paying kind) to create spiffy up-to-the minute tables, charts, and maps without the nuisance of manually exporting data to a spreadsheet, manipulating it, and creating a table, chart, or map.

EndNotes

[1] These fields are for illustrative purposes only. The DBViewer can work with any relational database that supports SQL. The only significant setup required is to create a table that acts like a data dictionary.

[2] The SQLs must be created dynamically because they generally include criteria such as "get me the last two months of data," or "get me the top ten percent of these values." This means that it is not possible to simple store the actual SQL statement and retrieve it for later use.

[3] Although this process sounds similar to calling an exported function in a DLL, the COM solution is more robust and allows DLL calls to be correctly made even if the DLL was generated by another vendor's compiler or even in a completely different language. Even calling non-COM DLLs generated in C++ but from different vendors is problematic because different vendors implement the features of C++ differently (e.g., RTTI, exception handling). Chapter 1 of Essential COM by Don Box (Addison-Wesley. 1998) provides an excellent description of these issues.

References

Box, Don. Essential COM, Addison-Wesley, 1998.
Grimes, Dr. Richard, Alex Stockton, George Reilly, and Julian Templeman. Beginning ATL COM Programming. Wrox Press Ltd., 1998.
Templeman, Julian. Beginning MFC COM Programming. Wrox Press Ltd., 1997.

Following is an example of VBA code used to access the DocEngine using the COM server.  Similar code can be written in VB, VB Script for ASP, and other applications and/or languages, thus making one library available to a vast array of systems.

Sub Test1()
	Set dll = CreateObject("ComSample.DocEngineInterface")
	Dim str As Variant
	Dim blah As String
	str = dll.HelloWorld()
	blah = CStr(str)
	Worksheets("Sheet1").Range("E7").Select
	ActiveCell.Value = CStr(str)
End Sub

Download Demo and Source - [86] KB 



Comments

  • Leveraging C++ Applications Using COM

    Posted by Legacy on 10/30/2001 12:00am

    Originally posted by: Rachel

    The web page was too wide and had to scroll left to right constantly which made the reading more difficult.

    Reply
  • How to convert SDI (Recordset) appln to this type of com

    Posted by Legacy on 03/06/2000 12:00am

    Originally posted by: Pratap Bose

    I developed many application in MFC where I initialised and take pointer of all recordset classes in Document class(SDI) OnNewDocument(). Now I want to make COMs which will hold my business logic (database retrieval and updation). I have gone through ur example. Here What I feel that we do not need any DocEngine.dll for manipulating this. Straitway We can write database part in methods of the designed interface (like within HelloWorld we can put the logic and directly call the interface method). So I am confused. Pl clarify if I am wrong. Eagerly waiting for ur reply. I am studying books on ATL COM. Will it help me to make good COM program in MFC?

    -Pratap

    Reply
  • Is it a fake?

    Posted by Legacy on 02/10/1999 12:00am

    Originally posted by: Alex

    This article is very interesting, but the sample...
    The DlgView sample not really uses the ComSample server.
    It actually uses DocEngine2.dll directly by using exported class CSomethingComplicated.
    Probably the authors just confused the sample.

    Reply
  • Leveraging C++ Applications Using COM

    Posted by Legacy on 11/25/1998 12:00am

    Originally posted by: John Zhang

    A very attractive subject. I have some questions. Where can I find the
    two papes you wrote about converting an existing C++ application into COM
    code?

    I read some books about COM, they talk about .IDL file, and I noticed
    you have an .ODL file. What's the difference between the two? Which one
    people should use?

    thanks

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds