COM (C言語)

// http://www.asahi-net.or.jp/~KV8S-YJM/another/yja104.htm

////////////////////////////////////////////////////////////////
//・
//[VB ] z = obj.Calc( x, y );
//↓
//[C  ] p->vptr->Calc( (void*)オブジェクトポインタ, x, y, &z );

////////////////////////////////////////////////////////////////
//・COMの基本ヘッダファイル
#include "objbase.h"

////////////////////////////////////////////////////////////////
//・CLSIDとIIDの特定
//・CLSIDとIIDの定義

//1. VS6.0ツールの [OLE View] を起動
//2. [メニュー] → [File] → [View TypeLib...] → 調べるコンポーネント(DLL)を指定
//3. クラス(coclass)の "uuid" という属性がそのコンポーネントのCLSID(クラスID)である
//4. インターフェイス(interface)の "uuid" という属性がそのインターフェイスのIID(インターフェイスID)である。
//
//[uuid(---),version(---),custom(---,---)]
//library Project1
//{
// importlib("stdole2.tlb");
//
// interface _Test01;
//
// [odl, uuid(D1890A6C-B213-11D4-AFC1-00D0B7AD59E8), version(---), hidden, dual, nonextensible, oleautomation]
// interface _Test01 : IDispatch {
// [id(---)]
// HRESULT Calc( [in] long x, [in] long y, [out, retval] long* );
// };
//
// [uuid(D1890A6D-B213-11D4-AFC1-00D0B7AD59E8),version(---)]
// coclass Test01 {
// [default]
// interface _Test01;
// };
//};

#include "objbase.h" // COM

//CLSIDとIIDはGUID型として定義する
const GUID  CLSID_Test01 = {0xd1890A6d,0xB213,0x11d4,{0xaf,0xc1,0x00,0xd0,0xb7,0xad,0x59,0xe8}}; //CLSID
const GUID  IID_Test01 = {0xd1890a6c,0xb213,0x11d4,{0xaf,0xc1,0x00,0xd0,0xb7,0xad,0x59,0xe8}}; //IID  

////////////////////////////////////////////////////////////////
//・COMインターフェイスの定義

// 関数ポインタ配列の定義
// ※関数ポインタ配列 = VTable(Virtual function table)
// ※順番通りに記述すること(使用しない関数は "void* p1" というふうに定義しても良い)
// 各メソッドの第一引数はオブジェクト
struct TestVTable
{
// IUnknown
HRESULT (__stdcall *QueryInterface)(void* _this, IID* riid, void** ptr);
ULONG   (__stdcall *AddRef )(void* _this);
ULONG   (__stdcall *Release)(void* _this);
   // IDispatch
HRESULT (__stdcall *GetTypeInfoCount)(void* _this, UINT*);
HRESULT (__stdcall *GetTypeInfo)(void* _this, UINT, LCID, ITypeInfo**);
HRESULT (__stdcall *GetIdsOfNames)(void* _this, const IID*, OLECHAR**, UINT, LCID, DISPID*);
HRESULT (__stdcall *Invoke )(void* _this, DISPID, const IID*, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);
// カスタム
HRESULT (__stdcall *Calc )(void* _this, long x, long y, long* pRetValue);
};

// COMインターフェイスの定義
struct _ITest01
{
TestVTable *vptr;
};

int main()
{
// COMの初期化
::CoInitialize(0);

// COMインターフェイスのポインタ
_ITest01* p;

// インスタンスの作成(ロード)
HRESULT hResult = ::CoCreateInstance( (REFCLSID)CLSID_Test01,
0,
CLSCTX_INPROC_SERVER,
(REFIID)IID_Test01,
(LPVOID*)&p );
if( !SUCCEEDED(hResult) ){
printf("Error occured = %08x\n", hResult);
return 0;
}

// メソッド呼び出し
long x = 10;
long y = 20;
long z;
p->vptr->Calc( (void*)p, x, y, &z );
printf("z = %d\n", z);

// インスタンスの解放(明示的な削除はできない)
p->vptr->Release( (void*)p );

// COMの終了処理
::CoUninitialize();

return 0;
}
最終更新:2009年01月08日 13:20
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。