Click here to Skip to main content
12,634,651 members (25,932 online)
Click here to Skip to main content
Add your own
alternative version

Stats

123.8K views
27 bookmarked
Posted

Using a BSTR to Transport C++ Objects Across the DCOM Interface

, 22 Nov 1999
Rate this:
Please Sign up or sign in to vote.
<!-- STEP 2. Include download and sample image information -->

One problem that has frustrated me is the difficulty of building a large object on the SQL/MTS server and then using DCOM to deliver all that stuff to the client. The objective was to submit a query to the server which would then process through the database , build a complex object, that is an object with nested maps, lists and arrays of other objects, and return the whole result in usable form to the client.

The semantics of using a SAFEARRAY or a large set of COM properties is daunting to me. Since I don't need to make these complex objects available to VB or Java applications I can keep all the code in C++.

This approach takes advantage of the simple design of a BSTR which, as I understand it, is just a long pointer. What it points to is the address between a long int and a block of memory, actually the first byte of the memory block. The long int preceding the string memory contains the byte length of the memory block. Usually the memory block contains a null terminated array of 2 byte characters, but it can actually contain anything. Since COM/DCOM know how to marshall BSTRs across the network and process boundaries, anything that can be packed into a BSTR can be marshalled across.

The first step is to get the arbitrarily complex object packed into the BSTR. I used a CMemFile to receive the serialized object, then stuff the CMemFile into the BSTR.

The code looks like this:

BSTR CMyView::FetchObject(long lParam)  // pseudo-server function
{
    MyComplexClass     *p_mCC;   // a serializable class
    BSTR               bstrHoldThis;
    CMemFile           mfFile;  // works just like a real
    // file
    
    
    CArchive  ar((CFile*)&mfFile, CArchive::store);
    
    // Create the complex object.  I include this stub here to indicate
    // that what is being passed is really an an object and not a pointer.
    // It could be a megabyte or more in size.
    
    p_mCC = new MyComplexObject(lParam);
    
    // A small, simple object could have been created on the stack.That's
    // not best place for a REALLY big object, although it
    // guarantees that it will go away when the function returns.
    // I generally put objects on the heap with 'new' and
    // delete them after serialization.
    
    // Serialize the object to the memory file
    p_mCC->Serialize(ar);
    
    // You need to flush the archive and file buffers
    ar.Flush();                 // flush the archive first
    mfFile.Flush();             // then the file
    
    // The step that creates the BSTR needs the length of the file
    
    ULONG lArchiveLength = mfFile.GetLength();
    
    // Stuff the archive into the BSTR with SysAllocStringByteLen()
    // CMemFile.Detach() returns a pointer to the memory block of the file
    // which is used to create the BSTR.
    
    bstrHoldThis = SysAllocStringByteLen((const char*)mfFile.Detach(),
        lArchiveLength);
    
    // Free the object.  The CMemFile will clean up after itself.
    
    delete p_mCC;
    
    // Return the BSTR result;
    
    return bstrHoldThis;  // send the whole thing into the aether
}

Now the caller needs to be able to unpack the BSTR and re-create the object. This is just the reverse of the steps above and I'd leave it as an exercise for the reader but I actually got it to work so here it is.

Void CMyView::OnButton1()
{
    BSTR   bstrA;
    MyComplexClass mRC;
    CMemFile   mfFile;
    
    // error checking omitted for clarity - but necessary
    
    // go get the BSTR wrapped object from the pseudo-server
    BstrA = FetchObject(m_lTestVal);
    
    // here's the ugly part. I back into the length of the BSTR.
    
    ULONG *p_lLength = (ULONG*) bstrA; // points at the byte AFTER the
    // BSTR length
    
    --p_lLength;    // now it points at the length of the
    // BSTR. Like Foster's - crude but
    // effective.
    
    // attach the memory part of the BSTR to the CMemFile memory block
    
    mfFile.Attach((unsigned char*) bstrA, *p_lLength);
    
    // now the object is in the memfile and it can be loaded
    CArchive ar(&mfFile, CArchive::load);
    
    mRC.Serialize(ar);
    
    // The object is now fully instantiated on the stack.
    // In this sample code it would be destroyed when this
    // function returned so you'd really want to build it with 'new'
    // on the heap and assign it to a member variable, or a
    // Document data member.
    
    // We still need to free the memory used by the BSTR and the
    // CMemFile. They both point to the same memory. The CMemFile
    // won't automatically free the memory that was attached when it
    // is destroyed, so freeing the BSTR memory takes care of that for us.
    
    SysFreeString(bstrA);
}

One could combine this method with others on a more general COM interface and agree to limit its use to MFC C++ clients (more non-portable ugliness). The challenge is to get all the serialization parts right for the array, maps, lists etc

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Richard Warg
United States United States
Dick Warg is very old, 60 in fact.
Dick thinks FORTH is still cool but he mostly writes dreadful C++ which ends up looking a lot like FORTH anyway when he gets done with it. He hopes to finish his current project real soon, or at least before his Social Security kicks in.

Favorite saying: "Who wrote this garbage? Oh, I did."

You may also be interested in...

Pro
Pro

Comments and Discussions

 
GeneralMy vote of 5 Pin
manoj kumar choubey25-Apr-13 4:40
membermanoj kumar choubey25-Apr-13 4:40 
GeneralHANDLE to BSTR Pin
Le Saint4-Jul-06 23:39
memberLe Saint4-Jul-06 23:39 
GeneralBSTR* eMvc++ Pin
sjsankar16-Nov-05 0:55
membersjsankar16-Nov-05 0:55 
GeneralBSTR* Pin
Manikandan20-Apr-05 6:22
memberManikandan20-Apr-05 6:22 
GeneralSerializing Data from C++ over a socket stream using tcp to a Java program Pin
SeanV23-Jul-03 3:56
memberSeanV23-Jul-03 3:56 
GeneralRe: Serializing Data from C++ over a socket stream using tcp to a Java program Pin
Anonymous30-Sep-04 17:11
sussAnonymous30-Sep-04 17:11 
QuestionHow to Set/Get string property with embedded null chars within Pin
Michael RENARD29-Jul-00 0:01
sussMichael RENARD29-Jul-00 0:01 
GeneralWill CArchive emulate compression or encryption... Pin
brandonl_webguy27-Jul-00 6:55
sussbrandonl_webguy27-Jul-00 6:55 
Generalrevised... Will CArchive emulate compression or encryption...revised Pin
brandonl_webguy27-Jul-00 7:01
sussbrandonl_webguy27-Jul-00 7:01 
GeneralEven Worse Pin
Dick Warg26-Jul-00 11:48
sussDick Warg26-Jul-00 11:48 
GeneralThere may be a better way... Pin
Chris Osborn24-Jul-00 10:58
sussChris Osborn24-Jul-00 10:58 
GeneralA Way to Send C++ Objects Pin
Brian Hart22-Jul-00 19:44
sussBrian Hart22-Jul-00 19:44 
GeneralRe: A Way to Send C++ Objects Pin
Shaj Fasul28-Sep-00 20:49
sussShaj Fasul28-Sep-00 20:49 
GeneralRe: A Way to Send C++ Objects Pin
azharuddin15-Dec-00 6:18
memberazharuddin15-Dec-00 6:18 
GeneralAll said and done Pin
vijaykumar goswami16-May-00 9:56
sussvijaykumar goswami16-May-00 9:56 
GeneralBSTR to LPCTSTR and Back Pin
PHIL31-Jan-00 13:37
sussPHIL31-Jan-00 13:37 
GeneralRe: BSTR to LPCTSTR and Back Pin
Jim Howard15-Dec-00 6:58
memberJim Howard15-Dec-00 6:58 
GeneralYou break the semantics of BSTR Pin
Johnny Xia26-Jan-00 20:05
sussJohnny Xia26-Jan-00 20:05 
GeneralRe: You break the semantics of BSTR Pin
Joe O'Leary4-Feb-00 20:39
sussJoe O'Leary4-Feb-00 20:39 
GeneralRe: You break the semantics of BSTR Pin
Ray Auchterlounie17-Feb-00 3:31
sussRay Auchterlounie17-Feb-00 3:31 
GeneralRe: You break the semantics of BSTR Pin
Steven1-Mar-00 2:12
sussSteven1-Mar-00 2:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.161208.2 | Last Updated 23 Nov 1999
Article Copyright 1999 by Richard Warg
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid