はじめに
VARIANT 型は Visual Basic.NET では使われませんが、以前の Visual Basic 6.0 ではよく使われていました。また、VBA や VBS (内部的に) では使用されています。
COM はこれらの言語に対応しているので、VARIANT 型データを扱うようになっています。そして、VARIANT 型のラッパーとして ATL CComVariant クラスがあります。このクラスを使うと、VARIANT 型を直接扱うより処理が簡単になります。
必要なヘッダー: atlcomcli.h
CComVariant の機能
コンストラクタ
変数から直接、CComVariant オブジェクトを作成できます。例えば、LPCSTR 型変数から文字列の VARIANT を作れます。何も指定しなければ、空の VARIANT を作れます。その他にも多くのバージョンがあります。(下記)
- CComVariant() throw();
- CComVariant(const CComVariant& varSrc);
- CComVariant(const VARIANT& varSrc);
- CComVariant(LPCOLESTR lpszSrc);
- CComVariant(LPCSTR lpszSrc);
- CComVariant(bool bSrc);
- CComVariant(BYTE nSrc) throw();
- CComVariant(int nSrc, VARTYPE vtSrc = VT_I4) throw();
- CComVariant(unsigned int nSrc, VARTYPE vtSrc = VT_UI4) throw();
- CComVariant(shor nSrc) throw();
- CComVariant(unsigned short nSrc) throw();
- CComVariant(long nSrc, VARTYPE vtSrc = VT_I4) throw();
- CComVariant(unsigned long nSrc) throw();
- CComVariant(LONGLONG nSrc) throw();
- CComVariant(ULONGLONG nSrc) throw();
- CComVariant(float fltSrc) throw();
- CComVariant(double dblSrc, VARTYPE vtSrc = VT_R8) throw();
- CComVariant(CY cySrc) throw();
- CComVariant(IDispatch* pSrc) throw();
- CComVariant(IUnknown* pSrc) throw();
- CComVariant(const SAFEARRAY* pSrc);
- CComVariant(char cSrc) throw();
- CComVariant(const CComBSTR& bstrSrc);
メソッド
- HRESULT CComVariant::Attach(VARIANT pSrc)* VARIANT 型変数をアタッチする。
- HRESULT CComVariant::ChangeType(VARTYPE vtNew, const VARIANT pSrc = NULL)* VARIANT の型を変更する。デフォルトでは値は NULL になる。
- HRESULT CComVariant::Clear() 中身をクリアする。
- HRESULT CComVariant::Copy(const VARIANT pSrc)* VARIANT 型変数の中身をこのオブジェクトにコピーする。
- HRESULT CComVariant::CopyTo(BSTR pstrDest)* このオブジェクトの中身を対象(BSTR型)にコピーする。このメソッドは VARTYPE が VT_BSTR のみ使用可能。
- HRESULT CComVariant::Detach(VARIANT pDest)* VARIANT 型変数にデタッチする。
- ULONG CComVariant::GetSize() const VARTYPE を含むサイズを返す。
- HRESULT CComVariant::ReadFromStream(IStream pStream)* IStream* 型のストリームから VARIANT を読み込んで自分の値とする。
- void CComVariant::SetByRef(T pT)* 自分の VARIANT をパラメータで初期化し VRATYPE に VT_BYREF 型を追加する。
- HRESULT CComVariant::WriteToStream(IStream pStream)* IStream* 型のストリームに自 VARIANT を書き込む。
演算子
以下のような代入演算子と比較演算子が用意されている。
- CComVariant::operator = このオブジェクトを対象のオブジェクトに代入する。下記のバージョンがある。
- CComVariant& operator=(const CComVariant& varSrc);
- CComVariant& operator=(const VARIANT& varSrc);
- CComVariant& operator=(const CComBSTR& bstrSrc);
- CComVariant& operator=(LPCOLESTR lpszSrc);
- CComVariant& operator=(LPCSTR lpszSrc);
- CComVariant& operator=(bool bSrc);
- CComVariant& operator=(BYTE nSrc) throw();
- CComVariant& operator=(int nSrc) throw();
- CComVariant& operator=(unsigned int nSrc) throw();
- CComVariant& operator=(short nSrc) throw();
- CComVariant& operator=(unsigned short nSrc) throw();
- CComVariant& operator=(long nSrc) throw();
- CComVariant& operator=(unsigned long nSrc) throw();
- CComVariant& operator=(LONGLONG nSrc) throw();
- CComVariant& operator=(ULONGLONG nSrc) throw();
- CComVariant& operator=(float fltSrc) throw();
- CComVariant& operator=(double dblSrc) throw();
- CComVariant& operator=(CY cySrc) throw();
- CComVariant& operator=(IDispatch* pSrc) throw();
- CComVariant& operator=(IUnknown* pSrc) throw();
- CComVariant& operator=(const SAFEARRAY* pSrc);
- CComVariant& operator=(char cSrc) throw();
- CComVariant::operator == このオブジェクトと VARIANT が等しいかを示す。
- CComVariant::operator != このオブジェクトと VARIANT が等しくないかを示す。
- CComVariant::operator < このオブジェクトより小さいかを示す。
- CComVariant::operator > このオブジェクトより大きいかを示す。
VARTYPE について
VARIANT 型は様々な型の変数を収容できる構造体ですが、元々は BASIC 言語 (Visual Basic の先祖) で使われていたものです。そして、VARIANT は Visual C++ では次のように定義されています。
typedef struct tagVARIANT {
union {
struct __tagVARIANT {
VARTYPE vt;
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
union {
LONGLONG llVal;
LONG lVal;
BYTE bVal;
SHORT iVal;
FLOAT fltVal;
DOUBLE dblVal;
VARIANT_BOOL boolVal;
_VARIANT_BOOL bool;
SCODE scode;
CY cyVal;
DATE date;
BSTR bstrVal;
IUnknown *punkVal;
IDispatch *pdispVal;
SAFEARRAY *parray;
BYTE *pbVal;
SHORT *piVal;
LONG *plVal;
LONGLONG *pllVal;
FLOAT *pfltVal;
DOUBLE *pdblVal;
VARIANT_BOOL *pboolVal;
_VARIANT_BOOL *pbool;
SCODE *pscode;
CY *pcyVal;
DATE *pdate;
BSTR *pbstrVal;
IUnknown **ppunkVal;
IDispatch **ppdispVal;
SAFEARRAY **pparray;
VARIANT *pvarVal;
PVOID byref;
CHAR cVal;
USHORT uiVal;
ULONG ulVal;
ULONGLONG ullVal;
INT intVal;
UINT uintVal;
DECIMAL *pdecVal;
CHAR *pcVal;
USHORT *puiVal;
ULONG *pulVal;
ULONGLONG *pullVal;
INT *pintVal;
UINT *puintVal;
struct __tagBRECORD {
PVOID pvRecord;
IRecordInfo *pRecInfo;
} __VARIANT_NAME_4;
} __VARIANT_NAME_3;
} __VARIANT_NAME_2;
DECIMAL decVal;
} __VARIANT_NAME_1;
} VARIANT, *LPVARIANT, VARIANTARG, *LPVARIANTARG;
中身の変数の型が何かは VARIANT 構造体の vt 変数で知ることができます。vt の型は VARTYPE ですが、次のように定義されています。
typedef unsigned short VARTYPE;
VARTYPE の値は次のようなシンボルで定義されています。
- VT_ARRAY SAFEARRAY のポインタ
- VT_BLOB Indicates length prefixed bytes.
- VT_BLOB_OBJECT Indicates that a blob contains an object.
- VT_BOOL ブール型
- VT_BSTR BSTR 型文字列
- VT_BYREF 参照型であることを示す。
- VT_CARRAY C スタイル配列
- VT_CF Clipboard フォーマット
- VT_CLSID クラスID
- VT_CY CURRENCY 型
- VT_DATE DATE 型
- VT_DECIMAL 10進数
- VT_DISPATCH IDispatch ポインタ
- VT_EMPTY 値が未定義であることを示す。
- VT_ERROR SCODE 型
- VT_FILETIME FILETIME 型
- VT_HRESULT HRESULT 型
- VT_I1 char 型
- VT_I2 short 型
- VT_I4 long 型 (32bit). COM では 32bit 整数は LONG と定義される。
- VT_I8 64-bit 整数型 (LONG LONG)
- VT_INT 整数
- VT_LPSTR NULL 終端された文字列
- VT_LPWSTR NULL 終端されたワイド文字列
- VT_NULL NULL 値. SQL の NULL 相当
- VT_PTR ポインタ型
- VT_R4 float 型
- VT_R8 double 型
- VT_RECORD ユーザ定義型
- VT_SAFEARRAY SAFEARRAY 型. VARIANT の中では無効 (エラー) になる。
- VT_STORAGE Indicates that the name of a storage follows.
- VT_STORED_OBJECT Indicates that a storage contains an object.
- VT_STREAM Indicates that the name of a stream follows.
- VT_STREAMED_OBJECT Indicates that a stream contains an object.
- VT_UI1 BYTE 型
- VT_UI2 unsigned short 型
- VT_UI4 unsigned long 型 (32-bit)
- VT_UI8 64-bit unsigned integer.
- VT_UINT 符号なしの整数
- VT_UNKNOWN IUnknown ポインタ
- VT_USERDEFINED ユーザ定義型
- VT_VARIANT VARIANT のポインタ
- VT_VECTOR Indicates a simple, counted array.
- VT_VOID C の void 型
サンプル
ヘッダーファイル
// stdafx.h : 標準のシステム インクルード ファイルのインクルード ファイル、または
// 参照回数が多く、かつあまり変更されない、プロジェクト専用のインクルード ファイル
// を記述します。
//
# pragma once
# include "targetver.h"
# include <stdio.h>
# include <tchar.h>
// TODO: プログラムに必要な追加ヘッダーをここで参照してください
# include <atlcomcli.h>
# include <atlstr.h>
# include <atlsafe.h>
CPP ファイル
// TestCComVariant.cpp : アプリケーションのエントリ ポイントを定義します。
//
# include "stdafx.h"
//
// CComVariant のテスト
// ====================
int main()
{
// LONG 型の VARIANT
CComVariant v3(1000L);
printf_s("%s\n", v3.vt == VT_I4 ? "True" : "False"); // True になる。
// VARIANT に代入
VARIANT x = v3;
printf_s("%d\n", x.lVal);
// BSTR の CComVariant を作成
CComBSTR bv0(L"bv0");
CComVariant cv0(bv0);
wprintf_s(L"%s\n", cv0.bstrVal);
// VARIANT を作成
VARIANT cv1;
cv1.bstrVal = CComBSTR(L"VARIANT cv1");
cv1.vt = VT_BSTR;
// BSTR 型の VARIANT
CComVariant v1(cv1);
printf_s("%s\n", v1.vt == VT_BSTR ? "True" : "False"); // True になる。
wprintf_s(L"%s\n", v1.bstrVal);
// BSTR 型の VARIANT をアタッチ
CComVariant v2;
v2.Attach(&cv1);
printf_s("%s\n", v2.vt == VT_BSTR ? "True" : "False"); // True になる。
wprintf_s(L"%s\n", v2.bstrVal);
// 他の VARIANT の中身を自分にコピーする。
CComVariant x2;
x2.Copy(&v3);
printf_s("%d\n", x2.lVal);
// 自 BSTR を 他の BSTR へコピーする。
BSTR bstr;
v1.CopyTo(&bstr);
wprintf_s(L"%s\n", bstr);
getchar();
return 0;
}
Fig.1 サンプルの実行例