![]() |
|
||||
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.
![]()
// 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;
}
|