Visual C++ Extensions での ADO の例

このプログラムは、値がフィールドからどのように取得され、C++ 変数に変換されるかを示しています。

この例では、"スマート ポインタ" を利用しています。これにより、COM 固有の QueryInterface の呼び出しの詳細と、IADORecordBinding インターフェイスに必要な参照が自動的に処理されます。

スマート ポインタを使わない場合は、次のようにコーディングします。

IADORecordBinding   *picRs = NULL;
...
TESTHR(pRs->QueryInterface(
          __uuidof(IADORecordBinding), (LPVOID*)&picRs));
...
if (picRs) picRs->Release();

スマート ポインタを使う場合は、次のステートメントで IADORecordBinding インターフェイスから IADORecordBindingPtr 型を取得します。

_COM_SMARTPTR_TYPEDEF(IADORecordBinding, __uuidof(IADORecordBinding));

そして、次のようにポインタをインスタンス化します。

IADORecordBindingPtr picRs(pRs);

Visual C++ Extensions は Recordset オブジェクトが実装するので、スマート ポインタのコンストラクタである picRs は _RecordsetPtr ポインタ pRs を使います。コンストラクタは、pRs を使って QueryInterface を呼び出し、IADORecordBinding インターフェイスを検索します。

// Visual C++ Extensions Example
#import "c:\Program Files\Common Files\System\ADO\msado15.dll" \
   no_namespace rename("EOF", "EndOfFile")

#include <stdio.h>
#include <icrsint.h>
_COM_SMARTPTR_TYPEDEF(IADORecordBinding, __uuidof(IADORecordBinding));

inline void TESTHR(HRESULT _hr) { if FAILED(_hr) _com_issue_error(_hr); }

class CCustomRs : public CADORecordBinding
{
BEGIN_ADO_BINDING(CCustomRs)
   ADO_VARIABLE_LENGTH_ENTRY2(2, adVarChar, m_ch_fname, 
                        sizeof(m_ch_fname), m_ul_fnameStatus, false)
   ADO_VARIABLE_LENGTH_ENTRY2(4, adVarChar, m_ch_lname, 
                        sizeof(m_ch_lname), m_ul_lnameStatus, false)
END_ADO_BINDING()
public:
   CHAR    m_ch_fname[22];
   CHAR    m_ch_lname[32];
   ULONG   m_ul_fnameStatus;
   ULONG   m_ul_lnameStatus;
};

void main(void)
{
   ::CoInitialize(NULL);
   try 
      {
      _RecordsetPtr pRs("ADODB.Recordset");
      CCustomRs rs;
      IADORecordBindingPtr picRs(pRs);
      
      pRs->Open("SELECT * FROM Employee ORDER BY lname", 
         "dsn=pubs;uid=sa;pwd=;", 
         adOpenStatic, adLockOptimistic, adCmdText);
      
      TESTHR(picRs->BindToRecordset(&rs));

      while (!pRs->EndOfFile)
         {
      // Process data in the CCustomRs C++ instance variables.
         printf("Name = %s %s\n",
            (rs.m_ul_fnameStatus == adFldOK ? rs.m_ch_fname: "<Error>"), 
            (rs.m_ul_lnameStatus == adFldOK ? rs.m_ch_lname: "<Error>"));

      // Move to the next row of the Recordset. 
      // Fields in the new row will automatically be 
      // placed in the CCustomRs C++ instance variables.
   
         pRs->MoveNext();
         }
      }
   catch (_com_error &e )
      {
      printf("Error:\n");
      printf("Code = %08lx\n", e.Error());
      printf("Meaning = %s\n", e.ErrorMessage());
      printf("Source = %s\n", (LPCSTR) e.Source());
      printf("Description = %s\n", (LPCSTR) e.Description());
      }
   ::CoUninitialize();
}