LoginSignup
5
4

More than 5 years have passed since last update.

Visual Studio 2017 Visual C++ : COM データ型 VARIANT と CComVariant

Last updated at Posted at 2018-02-18

はじめに

VARIANT 型は Visual Basic.NET では使われませんが、以前の Visual Basic 6.0 ではよく使われていました。また、VBA や VBS (内部的に) では使用されています。

COM はこれらの言語に対応しているので、VARIANT 型データを扱うようになっています。そして、VARIANT 型のラッパーとして ATL CComVariant クラスがあります。このクラスを使うと、VARIANT 型を直接扱うより処理が簡単になります。

MSDN: CComVariant クラス

必要なヘッダー: 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;
}

SampleCComVariant.png

Fig.1 サンプルの実行例

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4