com组件实例_DCOM组件

(40) 2024-08-16 17:01:03

参考:

- VS: VS2015创建ATL
- VC:VC6.0创建ATL

实例

1. 包含两个接口: Student,Teacher
2. Student接口包含5个函数(方法)
3. Teacher接口包含3个函数(方法)

创建COM组件 ATL

1. 在接口对象文件("Student.h")添加以下代码:

// Student.h : CStudent 的声明 #pragma once #include "resource.h" // 主符号 #include <vector> #include "VsAtlProjectOne_i.h" #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA) #error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。" #endif using namespace ATL; using namespace std; struct Student { CHAR *pName; ULONG unNO; UINT unAge; CHAR *pAddress; }; // CStudent class ATL_NO_VTABLE CStudent : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CStudent, &CLSID_Student>, public IDispatchImpl<IStudent, &IID_IStudent, &LIBID_VsAtlProjectOneLib, /*wMajor =*/ 1, /*wMinor =*/ 0> { public: CStudent() { } DECLARE_REGISTRY_RESOURCEID(IDR_STUDENT) BEGIN_COM_MAP(CStudent) COM_INTERFACE_ENTRY(IStudent) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } private: //学生数据 vector<Student> m_vStudent; public: //增加学生信息 STDMETHOD(AddStuInfo)(CHAR* pStuName, ULONG unStuNO, UINT unStuAge, CHAR *pAddress); //通过姓名获取年龄 STDMETHOD(GetStuAgeFromName)(CHAR* pStuName, UINT* pStuAge); //通过姓名获取学号 STDMETHOD(GetStuNOFromName)(CHAR* pStuName, UINT* pnStuNO); //通过姓名获取地址 STDMETHOD(GetStuAddressFromName)(CHAR* pStuName, CHAR** pnStuAddress); //获取学生总数 STDMETHOD(GetStuNumber)(UINT* punStuNumber); }; OBJECT_ENTRY_AUTO(__uuidof(Student), CStudent) 

2. 在接口对象文件("Student.cpp")添加以下代码:

// Student.cpp : CStudent 的实现 #include "stdafx.h" #include "Student.h" // CStudent //增加学生信息 STDMETHODIMP CStudent::AddStuInfo(CHAR* pStuName, ULONG unStuNO, UINT unStuAge, CHAR *pAddress) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); Student StudentInst; StudentInst.pName = pStuName; StudentInst.unNO = unStuNO; StudentInst.unAge = unStuAge; StudentInst.pAddress = pAddress; m_vStudent.push_back(StudentInst); return S_OK; } //通过姓名获取年龄 STDMETHODIMP CStudent::GetStuAgeFromName(CHAR* pStuName, UINT* pStuAge) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); vector<Student>::iterator itStu; for (itStu = m_vStudent.begin(); itStu != m_vStudent.end(); itStu++) { if (strcmp((*itStu).pName, pStuName) == 0) { *pStuAge = (*itStu).unAge; break; } } return S_OK; } //通过姓名获取学号 STDMETHODIMP CStudent::GetStuNOFromName(CHAR* pStuName, UINT* pnStuNO) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); vector<Student>::iterator itStu; for (itStu = m_vStudent.begin(); itStu != m_vStudent.end(); itStu++) { if (strcmp((*itStu).pName, pStuName) == 0) { *pnStuNO = (*itStu).unNO; break; } } return S_OK; } //通过姓名获取地址 STDMETHODIMP CStudent::GetStuAddressFromName(CHAR* pStuName, CHAR** pnStuAddress) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); vector<Student>::iterator itStu; for (itStu = m_vStudent.begin(); itStu != m_vStudent.end(); itStu++) { if (strcmp((*itStu).pName, pStuName) == 0) { *pnStuAddress = (*itStu).pAddress; break; } } return S_OK; } //获取学生总数 STDMETHODIMP CStudent::GetStuNumber(UINT* punStuNumber) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); *punStuNumber = m_vStudent.size(); return S_OK; }

3. 在接口对象文件("Teacher.h")添加以下代码:

// Teacher.h : CTeacher 的声明 #pragma once #include "resource.h" // 主符号 #include <vector> #include "VsAtlProjectOne_i.h" struct Teacher { CHAR *pName; ULONG unNO; }; #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA) #error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。" #endif using namespace ATL; using namespace std; // CTeacher class ATL_NO_VTABLE CTeacher : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CTeacher, &CLSID_Teacher>, public IDispatchImpl<ITeacher, &IID_ITeacher, &LIBID_VsAtlProjectOneLib, /*wMajor =*/ 1, /*wMinor =*/ 0> { public: CTeacher() { } DECLARE_REGISTRY_RESOURCEID(IDR_TEACHER) BEGIN_COM_MAP(CTeacher) COM_INTERFACE_ENTRY(ITeacher) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } private: //老师信息 vector<Teacher> m_vTeacher; public: //增加老师信息 STDMETHOD(AddTeacherInfo)(CHAR* pTeaName, UINT unTeaNO); //通过姓名工号 STDMETHOD(GetTeaNOFromName)(CHAR* pTeaName, ULONG* unTeaNO); //获取老师总数 STDMETHOD(GetTeaNumber)(UINT* punTeaNumber); }; OBJECT_ENTRY_AUTO(__uuidof(Teacher), CTeacher) 

4. 在接口对象文件("Teacher.cpp")添加以下代码:

// Teacher.cpp : CTeacher 的实现 #include "stdafx.h" #include "Teacher.h" // CTeacher //增加老师信息 STDMETHODIMP CTeacher::AddTeacherInfo(CHAR* pTeaName, UINT unTeaNO) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); Teacher TeacherInst; TeacherInst.pName = pTeaName; TeacherInst.unNO = unTeaNO; m_vTeacher.push_back(TeacherInst); return S_OK; } //通过姓名工号 STDMETHODIMP CTeacher::GetTeaNOFromName(CHAR* pTeaName, ULONG* unTeaNO) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); vector<Teacher>::iterator itTea; for (itTea = m_vTeacher.begin(); itTea != m_vTeacher.end(); itTea++) { if (strcmp((*itTea).pName, pTeaName) == 0) { *unTeaNO = (*itTea).unNO; break; } } return S_OK; } //获取老师总数 STDMETHODIMP CTeacher::GetTeaNumber(UINT* punTeaNumber) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); *punTeaNumber = m_vTeacher.size(); return S_OK; } 

 5. 接口对外声明文件("VsAtlProjectOne.idl")添加以下代码:

// VsAtlProjectOne.idl : VsAtlProjectOne的 IDL 源 // // 此文件将由 MIDL 工具处理以 // 产生类型库(VsAtlProjectOne.tlb)和封送处理代码。 import "oaidl.idl"; import "ocidl.idl"; [ object, uuid(EA00B97F-C817-43B6-94A2-E3B52CAC9610), dual, nonextensible, pointer_default(unique) ] interface IStudent : IDispatch{ [id(1)] HRESULT AddStuInfo([in] CHAR* pStuName, [in] ULONG unStuNO, [in] UINT unStuAge, [in] CHAR* pStuAddress); [id(2)] HRESULT GetStuAgeFromName([in] CHAR* pStuName, UINT* pStuAge); [id(3)] HRESULT GetStuNOFromName([in] CHAR* pStuName, UINT* pnStuNO); [id(4)] HRESULT GetStuAddressFromName([in] CHAR* pStuName, CHAR** pnStuAddress); [id(5)] HRESULT GetStuNumber([out] UINT* punStuNumber); }; [ object, uuid(B6E8E710-37A4-49BD-9CD9-56313DF7AA59), dual, nonextensible, pointer_default(unique) ] interface ITeacher : IDispatch{ [id(1)] HRESULT AddTeacherInfo([in] CHAR* pTeaName, [in] UINT unTeaNO); [id(2)] HRESULT GetTeaNOFromName([in] CHAR* pTeaName, [out] ULONG* unTeaNO); [id(3)] HRESULT GetTeaNumber([out] UINT* punTeaNumber); }; [ uuid(284DA5FE-71F9-4D34-8656-EF28201C766C), version(1.0), ] library VsAtlProjectOneLib { importlib("stdole2.tlb"); [ uuid(44DFFA13-CA7A-447C-960C-A0) ] coclass Student { [default] interface IStudent; }; [ uuid(8F193EA0-0E18-415D-9F46-DCF3D82D5E1F) ] coclass Teacher { [default] interface ITeacher; }; }; import "shobjidl.idl"; 

调用COM组件 ATL

#include "stdAfx.h" #include "TestAtl.h" //导入组件 //将"VsAtlProjectOne.dll" 放到目录 "C:\Windows\System32" #import "VsAtlProjectOne.dll" no_namespace //如果不知道命名空间,需要加上 no_namespace void TestAtl() { //初始化组件 ::CoInitialize(NULL); //获取组件接口的SID(通过属性) CLSID sidStudent; HRESULT hStudent = ::CLSIDFromProgID(L"VsAtlProjectOne.Student", &sidStudent); if (hStudent == S_OK) { //获取接口对象(通过接口ID) IStudent *pStudent(NULL); hStudent = ::CoCreateInstance(sidStudent, NULL, CLSCTX_INPROC_SERVER, __uuidof(IStudent), (LPVOID *)&pStudent); //调用接口函数(通过接口对象) if (hStudent == S_OK) { hStudent = pStudent->AddStuInfo("赵四", , 88, "四川.长春"); if (hStudent == S_OK) { TRACE("\n查找学生成功\n"); } else { TRACE("\n增加学生失败\n"); return; } hStudent = pStudent->AddStuInfo("刘能", 168, 18, "吉林.长春"); if (hStudent == S_OK) { TRACE("\n增加学生成功\n"); } else { TRACE("\n增加学生失败\n"); return; } hStudent = pStudent->AddStuInfo("杨晓燕", 288, 28, "贵州.贵阳"); if (hStudent == S_OK) { TRACE("\n增加学生成功\n"); } else { TRACE("\n增加学生失败\n"); return; } hStudent = pStudent->AddStuInfo("王大拿", 888, 99, "辽宁.大连"); if (hStudent == S_OK) { TRACE("\n增加学生成功\n"); } else { TRACE("\n增加学生失败\n"); return; } hStudent = pStudent->AddStuInfo("谢广坤", 22222, 90, "辽宁.大连"); if (hStudent == S_OK) { TRACE("\n增加学生成功\n"); } else { TRACE("\n增加学生失败\n"); return; } UINT unStuAge = 0; hStudent = pStudent->GetStuAgeFromName("杨晓燕", &unStuAge); if (hStudent == S_OK) { TRACE("\n查找学生成功\n"); } else { TRACE("\n查找学生失败\n"); return; } UINT unStuNO = 0; hStudent = pStudent->GetStuNOFromName("王大拿", &unStuNO); if (hStudent == S_OK) { TRACE("\n查找学生成功\n"); } else { TRACE("\n查找学生失败\n"); return; } CHAR *pStuAddress; hStudent = pStudent->GetStuAddressFromName("刘能", &pStuAddress); if (hStudent == S_OK) { TRACE("\n查找学生成功\n"); } else { TRACE("\n查找学生失败\n"); return; } UINT unStuNumber(0); hStudent = pStudent->GetStuNumber(&unStuNumber); if (hStudent == S_OK) { TRACE("\n查找学生成功\n"); } else { TRACE("\n查找学生失败\n"); return; } } } CLSID sidTeacher; HRESULT hTeacher = ::CLSIDFromProgID(L"VsAtlProjectOne.Teacher", &sidTeacher); if (hTeacher == S_OK) { ITeacher *pTeacher; hTeacher = ::CoCreateInstance(sidTeacher, NULL, CLSCTX_INPROC_SERVER, __uuidof(ITeacher), (LPVOID *)&pTeacher); if (hTeacher == S_OK) { hTeacher = pTeacher->AddTeacherInfo("严守一", ); if (hTeacher == S_OK) { TRACE("\n添加老师成功\n"); } else { TRACE("\n添加老师失败\n"); } hTeacher = pTeacher->AddTeacherInfo("费默", 998); if (hTeacher == S_OK) { TRACE("\n添加老师成功\n"); } else { TRACE("\n添加老师失败\n"); } hTeacher = pTeacher->AddTeacherInfo("于文娟", 1314); if (hTeacher == S_OK) { TRACE("\n添加老师成功\n"); } else { TRACE("\n添加老师失败\n"); } ULONG unTeaNO(0); hTeacher = pTeacher->GetTeaNOFromName("费默", &unTeaNO); if (hTeacher == S_OK) { TRACE("\n查找老师成功\n"); } else { TRACE("\n查找老师失败\n"); } UINT unTeaNumber(0); hStudent = pTeacher->GetTeaNumber(&unTeaNumber); if (hStudent == S_OK) { TRACE("\n查找老师成功\n"); } else { TRACE("\n查找老师失败\n"); return; } } } //释放线程加载的组件,卸载线程所有的DLL ::CoUninitialize(); }

 

 

THE END

发表回复