The Wayback Machine - https://web.archive.org/web/20060901121415/http://www.codeguru.com:80/cpp/com-tech/activex/com/article.php/c5541/

CodeGuru
Earthweb Search
Forums Wireless Jars Gamelan Developer.com
CodeGuru Navigation
Visual C++ / C++
.Net / C#
Visual Basic
Video
Submit an Article
Discussion Forums
Resource Directory
Announcements
Book List
Book Reviews
Guru Lists
Guest Book
About Us
FAQs
Site Map
Member Sign In
User ID:
Password:
Remember Me:
Forgot Password?
Not a member?
Click here for more information and to register.

jobs.internet.com

internet.commerce
Partners & Affiliates
Promotional Gifts
GPS
Health Insurance
KVM Switches
Cheap Digital Camera
CRM Software
Web Design
Promotional Products
Computer Deals
Franchise Directory
Online Booking Hotels
Online Masters
Web Hosting Providers
New Car Prices



RSS Feeds

All

VC++/C++

.NET/C#

VB

See more EarthWeb Network feeds

Home >> Visual C++ / C++ >> COM-based Technologies >> ActiveX Programming >> General COM/DCOM

Whitepaper: Why Smart Money Trusts HP Integrity Servers w/ Itanium 2 Processors. Learn how global visionary companies are incorporating the Itanium and Integrity solution to their company�s success.

Passing C++ Classes Across DCOM
Rating: none

Eugene Khodakovsky (view profile)
November 6, 2001


(continued)

Embracing the full spectrum of developer needs including content supporting 64 bit, Multi-Core, Tools, and Optimization.
I/O Virtualization and AMD's IOMMU
AMD64's virtualization extensions provide hardware support for VMM CPU virtualization, but that's only half the picture. I/O virtualization is the other half, and it's critical, because without hardware, I/O virtualization requires the high overhead of device emulation. Read more.
DB2 9 on AMD: A Perfect Match
What happens when you pair IBM's latest and greatest data server, DB2 9, with AMD's leading-edge Opteron architecture? You get a blisteringly fast data server platform that makes the most of advances on both fronts. Learn how DB2 9 has been optimized for NUMA and x86-64 architecture, and how it works with AMD 64-bit multi-core. Read more.
Virtualization Using AMD Servers and libVirt
Virtualization as a tool for development and deployment has come of age. Hardware advancements from manufacturers like AMD, and software tools such as libVirt, make creating and managing virtual machines a breeze. Let's look at how AMD, Red Hat, and others are helping push the virtualization envelope. Read more.
Widen Your Opportunities with 64-Bit Compilers: Microsoft Visual Studio 2005
Explore the capabilities and feature set of AMDs 64-bit compiler solution contained in Microsofts Visual Studio. Read more.
For more relevant code samples, tutorials and editorials click here.

Sample Image

Environment: VC++ 6.0, NT 4.0,Win2000, Win95/98

Using COM technology to pass simple data like long, int, etc is easy, but what about structured data like C++ classes? Most developers knows the way to pass that. The way is generally based on passing data using VARIANT as SAFEARRAY. And what does VARIANT mean?

The VARIANT is perhaps the ultimate in general purpose functionality for passing data, but its range of low-level features can be daunting. I did not find a more suitable library that could easily be used one in my projects. For this reason, I built two classes that provide richer interfaces and easier semantics.

The first class is called CDComObj. This class is responsible for reading and writing data into and from VARIANT. The second class, CDcomObjArray, is responsible for passing a collection of objects across DCOM. By using both of these classes it is easy to implement any C++ class with the ability to pass itself across DCOM.

An Example Using the Objects

Client part:

bool CServerAccessPoint::ServerConnect(CConnection& connObj)
{
  CComSafeArray conn;
  connObj.Write(conn); // Writing C++ class to VARIANT

  HRESULT hr = m_pDcomServer->Connect(&conn);
  if (FAILED(hr))
  {
    // DO something...
    return false;
  }
  return true;
}

Server part:

STDMETHODIMP CStreamingSrv::Connect(VARIANT *pConnection)
{
  Lock();
  CConnection conn;
  conn.Read(pConnection); // Reading C++ class from VARIANT

  m_connections.AddConnection(conn);
  Unlock();
  return S_OK;
}

Is that not easy?

Classes

class CDcomObj  : public CSLObject
{
public
  CDcomObj();
  virtual ~CDcomObj();

  virtual void Clear();
  virtual void Copy(const CSLObject& objectSrc);
          void Copy(const CDcomObj& objectSrc);
  virtual bool IsEqual(const CSLObject& objectSrc);

  virtual HRESULT WriteToStream(IStream* pStream);
  virtual HRESULT ReadFromStream(IStream* pStream);

  virtual long ElementSize();
          void Write(VARIANT* pSafeArray);
          void Write(CComSafeArray* safeArray);
  virtual void Write(CComSafeArray* safeArray,long& index);

          void Read(const CLSID& clsid);
          void Read(VARIANT* pSafeArray);
          void Read(CComSafeArray* safeArray);
  virtual void Read(CComSafeArray* safeArray,long& index);
          void ReadValue(const CComVariant& srcValue,
                         CComVariant& destValue);
          void ReadValue(const CComVariant& srcValue,
                         CComPtr<IUNKNOWN>& destValue);
          void ReadValue(const CComVariant& srcValue,
                         IUnknown** destValue);
          void ReadValue(const CComVariant& srcValue,
                         CString& destValue);
          void ReadValue(const CComVariant& srcValue,
                         CComBSTR& destValue);
          void ReadValue(const CComVariant& srcValue,
                         LONG& destValue);
          void ReadValue(const CComVariant& srcValue,
                         CY& destValue);
          void ReadValue(const CComVariant& srcValue,
                         bool& destValue);
          void ReadValue(const CComVariant& srcValue,
                         UINT& destValue);
          void ReadValue(const CComVariant& srcValue,
                         DWORD& destValue);
          void ReadValue(const CComVariant& srcValue,
                         int& destValue);
          void ReadValue(const CComVariant& srcValue,
                         double& destValue);
          void ReadValue(const CComVariant& srcValue,
                         DATETIME_STRUCT& destValue);

          void ProgIDFromCLSID(const CLSID& clsid,
                               CComBSTR& comBSTR);

          const CLSID    GetCLSID();
          const CComBSTR GetLastError();
          const bool IsModified() const;
          const bool IsModified(UINT value) const;
          const UINT GetModified() const;
                void AddModified(UINT uModified);
                void SetModified(UINT uModified);
                void RemoveModified(UINT uModified);
                void ShowError(CString lpszError);

public:

    CComBSTR  m_strCLSID;
    CComBSTR  m_strProgID;
    CComBSTR  m_strObjectName;

protected:

    // Specifics
    UINT      m_uModified;
    CComBSTR  m_bstrError;
};

Using the classes, step by step

The implementation of own DCOM class is very easy.

Step 1: Create your own class derived from CDComObj.

 class CConnection : public CDcomObj

Step 2: Redefine the following virtual member functions:

// Shows how many elements contains your class
virtual long ElementSize()

// Writing class data to VARIANT (SAFEARRAY)
virtual void Write(CComSafeArray* safeArray,long& index);

// Reading class data from VARIANT (SAFEARRAY)
virtual void Read(CComSafeArray* safeArray,long& index);

// Copying data
virtual void Copy(const CSLObject& objectSrc);


// Clear data
virtual void Clear();

The DComObj contains the set of macros so the redefinitions of mentioned functions is easy

An Example

To demonstrate this technique I built two classes: CConnection and CConnectionArray

class CConnection  : public CDcomObj
{
  DCL_DCOMOBJ(CConnection)
public:
  CConnection();
  virtual ~CConnection();

  virtual void Clear();
  virtual void Copy(const CSLObject& objectSrc);
  virtual bool IsEqual(const CSLObject& objectSrc);
  virtual long ElementSize();
  virtual void Write(CComSafeArray* safeArray,long& index);
  virtual void Read(CComSafeArray* safeArray,long& index);

protected:

  CString   m_strComputerName;
  CString   m_strApplicationName;
  CString   m_strUserName;
  CString   m_strPassword;
  CString   m_strServerName;
  CComBSTR  m_strConnectionHandle;
};

Here is the implementation of ElementSize() member function

long CConnection::ElementSize()
{
  return 6 + CDcomObj::ElementSize();
}

The implementation of Write and Read member function you can find here.

void CConnection::Write(CComSafeArray* safeArray,long& index)
{
  SA_BEGIN_WRITE(CDcomObj);
  SA_WRITE(m_strComputerName);
  SA_WRITE(m_strUserName);
  SA_WRITE(m_strPassword);
  SA_WRITE(m_strServerName);
  SA_WRITE(m_strApplicationName);
  SA_WRITE(m_strConnectionHandle);
}

void CConnection::Read(CComSafeArray* safeArray,long& index)
{
  SA_BEGIN_READ(CDcomObj);
  SA_READ(m_strComputerName);
  SA_READ(m_strUserName);
  SA_READ(m_strPassword);
  SA_READ(m_strServerName);
  SA_READ(m_strApplicationName);
  SA_READ(m_strConnectionHandle);
}

For streaming the collection of CConnection objects across DCOM it is enough to define class like here.

class CConnectionArray : public CDcomObjArray
{
  DCL_DCOMOBJ_ARRAY(CConnectionArray,CConnection)
public:
  CConnectionArray(){}
  CConnectionArray( ccIndex aLimit,
                    ccIndex aDelta,
                    bool shouldDelete = true):
  CDcomObjArray(aLimit,aDelta ,shouldDelete )
  {
  }
  virtual ~CConnectionArray(){}

};

Notes

To avoid MFC at Server side, I am using a CString object from WTL V.3.1. You should download one from the Microsoft site. In any case don't forget to set up a path to this library in your Compiler: Tools/Options/Directories.

For easy manipulate with SafeArray, I am using the CComSafeArray class from www.sellsbrothers.com

The Demo project demonstrates the following:

  • Passing C++ class / collection of classes across COM/DCOM.
  • Connection Point Technique

How you can see that?

  1. Register Server by starting StreamingServer.exe with option 'RegServer' : StreamingServer.exe -RegServer.
  2. Start first instance of Client: StreamingClient.exe
  3. Connect to the server as some user
  4. Start another instance of Client
  5. Connect to server with different user name
  6. After establishing connection you can see list of connected users in any Client
  7. Start another instance and list of connected users will grow

What's going on?

Under connection stage client sending to the server C++ class CConnection. If server accepted this request it sending collection of CConnection classes to everything connected clients.

Downloads

Get DB2 Express-C 9. Free to Develop, Deploy, Distribute. No limits--just data. Download Now!
Developer.com Webcast: Defining Your Own Software Development Methodology.
Webcast: Linux on Multi-Core--WAS CE and the Open Stack Appliance
Webcast: Cingular Mobile Security Architecture--Get details on security issues, policies, and more.
Learn how to navigate the key issues that affect developing and deploying mobile applications.


RATE THIS ARTICLE:   Excellent  Very Good  Average  Below Average  Poor  

(You must be signed in to rank an article. Not a member? Click here to register)

Latest Comments:
Passing structure to event in ActvieX control - rajeshkapure (08/29/2005)
I think what DCOM do is to provide a new data type "remotable interface" - Legacy CodeGuru (03/31/2003)
A classical example of how NOT to use COM - Legacy CodeGuru (11/15/2001)
What's the point... - Legacy CodeGuru (11/07/2001)
Why use a CString? - Legacy CodeGuru (11/06/2001)

View All Comments
Add a Comment:
Title:
Comment:
Pre-Formatted: Check this if you want the text to display with the formatting as typed (good for source code)



(You must be signed in to comment on an article. Not a member? Click here to register)
Small Business Software Resources from Microsoft
Is Your Accounting Software Limiting Your Growth and Productivity?
Get Your FREE Financial Software Evaluation Kit Today!
This free Financial Software Evaluation Kit from Microsoft Dynamics GP will help you identify problems with your software, data management, reporting, and more.

JupiterWeb networks:

internet.comearthweb.comDevx.comGraphics.com

Search JupiterWeb:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterWeb

Jupitermedia Corporate Info