Are you a world traveler? ZoneTick is a cool utility that'll help you stay in touch over multiple time zones!
 
Passing VARIANTs between VB and VC++  
Nik Okuntseff  Windows 2000 Security Programming 

Passing VARIANTs between VB and VC++

Passing arguments from a Visual Basic program to a COM object written in C++ might get tricky. There are at least three ways a VB program can pass a string-based argument to a COM object. Depending on how VB code is written it may be passed as VT_BSTR, as VT_BYREF | VT_BSTR, or as VT_BYREF | VT_VARIANT.

Consider, for example, the following Visual Basic code:

Dim obj As Object
Set obj = CreateObject("VariantCom.VariantTester")
Dim strRetVal As String
'Pass VT_BSTR
strRetVal = obj.PassVariant("Hello, World!")
Set obj = Nothing

In the above example the VARIANT is transmitted as VT_BSTR. The fragment below will pass VT_BSTR by reference (the COM object will get VT_BSTR | VT_BYREF).

Dim obj As Object
Set obj = CreateObject("VariantCom.VariantTester")
Dim strRetVal As String
'Now pass VT_BYREF | VT_BSTR
Dim str As String
str = "Hello, World!"
strRetVal = obj.PassVariant(str)
Set obj = Nothing

Finally, this would pass a VARIANT by reference:

Dim obj As Object
Set obj = CreateObject("VariantCom.VariantTester")
Dim strRetVal As String
'Now pass VT_BYREF | VT_VARIANT
Dim var
var = "Hello, World!"
strRetVal = obj.PassVariant(var)
Set obj = Nothing

A VC++ based COM object should be able to distinguish between 3 different ways of passing a string and handle all of them properly. I am including a simple VC++ COM object with this book (App\VariantCom), as well as VB based tester application (App\VbVariantComTester). The section below describes how to create such simple COM object using VC++.
 

Creating a Simple COM Object in VC++

To create a simple COM object in Visual C++ that takes a VARIANT based string in and returns a VARIANT based string back follow these steps.

  • Launch Visual C++ and create a new ATL COM AppWizard project. Accept all default settings and build a project.
  • Insert a new ATL object in it. Go to Insert - New ATL Object menu, then select "Simple Object", click on the Next button, and name it.
  • Add a method to the object's interface. To do it right-click on the interface in ClassView and select Add Method... Type in parameters as shown on the figure below.

  • Write code for the method. Here is what I have in my VariantCom object.
// Test.cpp : Implementation of CTest
#include "stdafx.h"
#include "MyTest.h"
#include "Test.h"
#include <comdef.h>  // Needed for variant_t

/////////////////////////////////////////////////////////////////////////////
// CTest


STDMETHODIMP CTest::MyMethod(VARIANT v, VARIANT *pv)
{
  if(NULL == pv)
    return E_INVALIDARG;

  // Check type of the VARIANT.
  if(VT_BSTR == v.vt)
    ::MessageBox(NULL, TEXT("Variant type is VT_BSTR."), TEXT("VariantCom.VariantTester"), MB_OK | MB_ICONINFORMATION);
  else if((VT_BYREF | VT_BSTR) == v.vt)
    ::MessageBox(NULL, TEXT("Variant type is VT_BYREF | VT_BSTR."), TEXT("VariantCom.VariantTester"), MB_OK | MB_ICONINFORMATION);
  else if((VT_BYREF | VT_VARIANT) == v.vt)
    ::MessageBox(NULL, TEXT("Variant type is VT_BYREF | VT_VARIANT."), TEXT("VariantCom.VariantTester"), MB_OK | MB_ICONINFORMATION);
  else
    ::MessageBox(NULL, TEXT("Variant type is not VT_BSTR, VT_BYREF | VT_BSTR, or VT_BYREF | VT_VARIANT."), TEXT("VariantCom.VariantTester"), MB_OK | MB_ICONINFORMATION);

  // Handling different types is easy if we use variant_t.
  variant_t vtData = v;
  bstr_t btData = vtData;
  char * pszData = btData;
  ::MessageBox(NULL, pszData, "Data passed:", MB_OK | MB_ICONINFORMATION);

  // Pass something back.
  ::VariantClear(pv);
  bstr_t bstrData = "This string was generated in a VC++ based COM object...";
  pv->vt = VT_BSTR;
  pv->bstrVal = bstrData.copy();
  return S_OK;
}
  • When you have the COM object compiled you can reference it in a VB project and try to use it.

 
[ Contents | Home ]

Send comments and suggestions to niko@wrconsulting.com
Copyright © 2000 by Nik Okuntseff