IDispatch及双接口的调用
1,使用API方式调用:
1 ::CoInitialize( NULL ); // COM 初始化 2 3 CLSID clsid; // 通过 ProgID 得到 CLSID 4 HRESULT hr = ::CLSIDFromProgID( L"Simple8.DispSimple.1", &clsid ); 5 ASSERT( SUCCEEDED( hr ) ); // 如果失败,说明没有注册组件 6 7 IDispatch * pDisp = NULL; // 由 CLSID 启动组件,并得到 IDispatch 指针 8 hr = ::CoCreateInstance( clsid, NULL, CLSCTX_ALL, IID_IDispatch, (LPVOID *)&pDisp ); 9 ASSERT( SUCCEEDED( hr ) ); // 如果失败,说明没有初始化 COM 10 11 LPOLESTR pwFunName = L"Add"; // 准备取得 Add 函数的序号 DispID 12 DISPID dispID; // 取得的序号,准备保存到这里 13 hr = pDisp->GetIDsOfNames( // 根据函数名,取得序号的函数 14 IID_NULL, 15 &pwFunName, // 函数名称的数组 16 1, // 函数名称数组中的元素个数 17 LOCALE_SYSTEM_DEFAULT, // 使用系统默认的语言环境 18 &dispID ); // 返回值 19 ASSERT( SUCCEEDED( hr ) ); // 如果失败,说明组件根本就没有 ADD 函数 20 21 VARIANTARG v[2]; // 调用 Add(1,2) 函数所需要的参数 22 v[0].vt = VT_I4; v[0].lVal = 2; // 第二个参数,整数2 23 v[1].vt = VT_I4; v[1].lVal = 1; // 第一个参数,整数1 24 25 DISPPARAMS dispParams = { v, NULL, 2, 0 }; // 把参数包装在这个结构中 26 VARIANT vResult; // 函数返回的计算结果 27 28 hr = pDisp->Invoke( // 调用函数 29 dispID, // 函数由 dispID 指定 30 IID_NULL, 31 LOCALE_SYSTEM_DEFAULT, // 使用系统默认的语言环境 32 DISPATCH_METHOD, // 调用的是方法,不是属性 33 &dispParams, // 参数 34 &vResult, // 返回值 35 NULL, // 不考虑异常处理 36 NULL); // 不考虑错误处理 37 ASSERT( SUCCEEDED( hr ) ); // 如果失败,说明参数传递错误 38 39 CString str; // 显示一下结果 40 str.Format("1 + 2 = %d", vResult.lVal ); 41 AfxMessageBox( str ); 42 43 pDisp->Release(); // 释放接口指针 44 ::CoUninitialize(); // 释放 COM
2,使用智能指针包装类:
1 // 在 App 类,InitInstance 中,已经调用 AfxOleInit() 进行了 COM 初始化 2 3 CLSID clsid; // 通过 ProgID 取得组件的 CLSID 4 HRESULT hr = ::CLSIDFromProgID( L"Simple8.DispSimple.1", &clsid ); 5 ASSERT( SUCCEEDED( hr ) ); // 如果失败,说明没有注册组件 6 7 CComPtr < IUnknown > spUnk; // 由 CLSID 启动组件,并取得 IUnknown 指针 8 hr = ::CoCreateInstance( clsid, NULL, CLSCTX_ALL, IID_IUnknown, (LPVOID *)&spUnk ); 9 ASSERT( SUCCEEDED( hr ) ); 10 11 CComDispatchDriver spDisp( spUnk ); // 构造只能指针 12 CComVariant v1(1), v2(2), vResult; // 参数 13 hr = spDisp.Invoke2( // 调用2个参数的函数 14 L"Add", // 函数名是 Add 15 &v1, // 第一个参数,值为整数1 16 &v2, // 第二个参数,值为整数2 17 &vResult); // 返回值 18 ASSERT( SUCCEEDED( hr ) ); // 如果失败,说明或者没有 ADD 函数,或者参数错误 19 20 CString str; // 显示一下结果 21 str.Format("1 + 2 = %d", vResult.lVal ); 22 AfxMessageBox( str ); 23 24 // spUnk 和 spDisp 都是智能指针,会自动释放 25 // 如果使用 CoInitialize(NULL) 初始化,则必须在 CoUninitialize() 之前 26 // 调用 spUnk.Release() 和 spDisp.Release() 释放
3,加载类型库、产生包装类来使用。
添加类->类型库中的MFC类;选择组件文件(dll或者tlb文件)和需要包装的接口。
调用代码:
1 #include "CDispSimple.h" // 包装类的头文件 2 3 void demo() 4 { 5 // 已经进行过了 COM 初始化 6 7 CDispSimple spDisp; // 包装类的对象 8 spDisp.CreateDispatch( _T("Simple8.DispSimple.1") ) // 启动组件 9 spDisp.xxx(...); // 调用函数 10 11 spDisp.ReleaseDispatch(); // 释放接口 12 }
4,使用#import方式调用组件(效率最高)。