COM组件 ATL的创建和调用

1 篇文章 0 订阅

参考:

- 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-1676644028A0)		
	]
	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("赵四", 123456789, 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("严守一", 123456);
			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();
}

 

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值