COM/DCOM开发练习之进程内组件实例

作者 : 卿笃军

题目说明:

仿照例题,在其基础上实现以下功能:

1)使用C++语言实现进程内组件,组件提供复数的加、减、乘、除等计算服务;客户端部分包括录入(实部和虚部分开录入)和查询部分。

2)在VC++环境上利用ATL向导进行开发。

3)至少实现三种运行模式中的两种。

4) 程序设计风格良好,有文档注释,方法注释,语句注释。并附带说明文档。

5)下周六晚10点前统一发至我邮箱。

开工、首先编写服务器端利用ATL COM AppWizard开发出 CalcSvr.dll

第一步:打开VC++6.0选择 ATL COM AppWizard ,然后在工程名处输入 CalcSvr  目录我们这里选择  E:\Ock

点击确定,进入下一步后,全部默认,点击完成!

第二步:开始创建我们的ATL类了,其作用就是实现.dll的功能。

点击插入->类    如下图:

然后,开始创建ATL类,类的类型选择 ATL Class,类名称我这里输入CCalcMath,其它不要动,点击确定。

第三步:添加类方法,看到刚才创建的那个CCalcMath类了吧?右击ICalcMath然后选择Add Method添加方法。

第四步:输入类名和类参数,注意这里类参数直接用逗号分开就行了,也不需要写成如下形式:

[in] int Num1, [in] int Num2, [out] int *result

这个[in],[out]是VS里面的,VS里面是设计成了复选框,直接点击的。

自己仿照上面的加法操作,将减法,乘法,除法,素数~~全部添加好。

需要注意的是,类参数时根据你自己的需要设定的,比如,你判断一个数字是不是素数,这时候只需要两个参数,一个传进来,一个表示传出结果。

第五步:实现类功能。类已经全部添加好了,我们现在实现一下类功能就OK了。

点击InterfaceSupportsErrorInfo可以进入实现页面,当然,你也可以直接点击CCalcMath.cpp

第六步:分别实现 Add(), Sub(),Mul(), Div(),Sushu() 加,减,乘,除,素数这4个函数的功能:

下面是全部实现代码,其实就添加了几行代码~~~你只需要看着四个函数里面添加的内容就行了。

因为下面的代码,很多是类向导自动生成的。

// CalcMath.cpp : Implementation of CCalcSvrApp and DLL registration.
#include "stdafx.h"
#include "CalcSvr.h"
#include "CalcMath.h"
#include <math.h>

/////////////////////////////////////////////////////////////////////////////
//

STDMETHODIMP CCalcMath::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] =
	{
		&IID_ICalcMath,
	};

	for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
	{
		if (InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}

STDMETHODIMP CCalcMath::Add(double Num1, double Num2, double *result)
{
	// TODO: Add your implementation code here
	*result = Num1 + Num2;
	return S_OK;
}

STDMETHODIMP CCalcMath::Sub(double Num1, double Num2, double *result)
{
	// TODO: Add your implementation code here
	*result = Num1 - Num2;
	return S_OK;
}

STDMETHODIMP CCalcMath::Mul(double Num1, double Num2, double *result)
{
	// TODO: Add your implementation code here
	*result = Num1 * Num2;
	return S_OK;
}

STDMETHODIMP CCalcMath::Div(double Num1, double Num2, double *result)
{
	// TODO: Add your implementation code here
	if (Num2 != 0)
		*result = Num1 / Num2;
	return S_OK;
}

STDMETHODIMP CCalcMath::Sushu(int Num, int *result)
{
	// TODO: Add your implementation code here
	int i = 0;

	for(i = 2; i <= sqrt(Num); i++)   //记得加上 #include <math.h>
    {
        if((Num % i) == 0)
		{
            *result = 0;    //0表示非素数
			break;
		}
    }
	if (i > sqrt(Num))
		*result = 1;        //1表示是素数

	return S_OK;
}

第七步:编译->链接。好了,我们的服务器端已经编写好了。

这时候,你在工程目录下面的Debug里面会看到CalcSvr.dll,同时注意上面的路径,因为你现在要手动注册CalcSvr.dll

第八步:注册CalcSvr.dll。

调出dos窗口。你可以按住win+R呼出运行,或者直接在开始栏里面点击运行,然后输入 cmd

执行注册的时候,需要注意.dll的路径

首先,进入dll所在的那个磁盘,如我的在E盘,则输入如下:

E:

然后进入相应的文件夹,cd表示进入该文件夹~,输入如下命令:

cd Ock\CalcSvr\Debug

服务器端,我们已经编写好了,下面我们来编写客户端。

这里就不用MFC了,为了简洁明了起见,直接创建一个win32控制台应用程序。win32控制台应用程序具体创建不说了,只要写过Hello World的都会。

下面编写客户端应用程序。

第一步:win32控制台应用程序 工程命名为 CalcClient,然后创建C++ Source File的时候也命名为:CalcClient.cpp。

第二步:将开始我们编写服务器端的时候,工程目录下的CalcSvr.h 和 CalcSvr_i.c两个文件拷贝过来,放在客户端工程目录下面。

第三步:在CalcClient.cpp里面,编写客户端具体实现代码。

#include <windows.h>
#include <iostream>
#include "CalcSvr.h"
#include "CalcSvr_i.c"
using namespace std;

template< class T >   //函数模板
void show( T t )
{
	cout << t << endl;
}

void DCOM()
{
	double data = 0.0;
	int flag = 0;
	double a = 0.0, b = 0.0;
	//初始化COM库
	HRESULT hr=::CoInitialize(NULL);   //用来告诉Windows以单线程的方式创建COM对象
	if( !SUCCEEDED( hr ) )
	{
		show( "init right failed!" );
	}
	ICalcMath *plRF = NULL;
	hr=::CoCreateInstance(CLSID_CalcMath,NULL,CLSCTX_INPROC_SERVER,IID_ICalcMath,(LPVOID *)&plRF);//用指定的类标识符在本地创建一个未初始化的COM对象
	if(FAILED(hr))
	{
		cout<<"创建组件实例失败"<<endl;
	}
	//调用方法
	cout<<"请选择:1.加;2.减;3.乘;4.除;5.判断素数(注:1表示素数;0表示非素数);0.退出\n__\b\b";
	cin>>flag;
	while(flag!=0)
	{
		switch(flag)
		{
		case 1:
			{
				cout<<"请输入要相加的两个数字:" ;
				cin>>a>>b;
				plRF->Add(a,b,&data);
				cout<<"计算结果为:";
				show( data );
				break;
			}
		case 2:
			{
				cout<<"请输入要相减的两个数字:" ;
				cin>>a>>b;
				plRF->Sub(a,b,&data);
				cout<<"计算结果为:";
				show( data );
				break;
			}
		case 3:
			{
				cout<<"请输入要相乘的两个数字:" ;
				cin>>a>>b;
				plRF->Mul(a,b,&data);
				cout<<"计算结果为:";
				show( data );
				break;
			}
		case 4:
			{
				cout<<"请输入要相除的两个数字:" ;
				cin>>a>>b;
				if (b-0<1e-5 || 0-b>1e-5)
				{
					cout<<"除数不能为0\n";
					break;
				}
				plRF->Div(a,b,&data);
				printf("计算结果为:");
				show( data );
				break;
			}
		case 5:
			{
				cout<<"请输入要进行判断的数字:" ;
				cin>>a;
				plRF->Sushu((int)a,(int *)&data);
				cout<<"判断结果为:";
				show( data );
				break;
			}
		case 0:break;
		default:break;
		}
		system("pause");
		system("cls");
		cout<<"请选择:1.加;2.减;3.乘;4.除;5.判断素数(注:1表示素数;0表示非素数);0.退出\n__\b\b";
		cin>>flag;
	}
	plRF->Release();
	CoUninitialize(); //CoUninitialize关闭当前线程的COM库,卸载线程加载的所有dll,释放任何其他的资源,关闭在线程上维护所有的RPC连接。
}
int main()
{
	DCOM();

	return 0;
}
/*
ps:
//#define _WIN32_DCOM //#if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM
*/

第四步:编译->链接->运行。

参考文献:qipanlimingCSDN博客的专栏,COM/DCOM开发练习之进程内组件实例,http://blog.csdn.net/lican19911221/article/details/7459983,2014年5月13日

COM/DCOM开发练习之进程内组件实例

时间: 2024-10-27 07:43:44

COM/DCOM开发练习之进程内组件实例的相关文章

在VC6.0下如何调用Delphi5.0开发的进程内COM

因为本人的语言水平很差,考大学时150的总分,我考了个60分.外语也是,初中及格过一次,会考及格过一次.其它的时间好像从没有及格过.所以我不写文章,因我一百字的文章给我写,至少要出八九个错别字.哈哈….真是个马大哈.你别说我还真的姓马.所以下面的文章中有错误之处,请你老人家多多理解.谁叫你看我的文章了的.下面就谈正事吧! 本人接触COM的时间也不长,是看了本关于组件重用的书,才让我对COM产生性(兴)趣的.所以就想试试COM的二进制级重用好不好用.在开发公司项目的过程中,我就用COM方式写了一个

Android 子Activity组件在进程内的启动过程 &amp;&amp; 子Activity组件在新进程中的启动过程

1.子Activity组件在进程内的启动过程 在Android Activity组件的启动过程http://blog.csdn.net/jltxgcy/article/details/35984557一文中,我们已经详细分析了Activity的启动过程,对于子Activity组件在进程内的启动过程,我们只分析它们之间的不同. 主要是2处,1是不需要创建新的任务栈,2是不需要创建新进程和子线程. 第1点,体现在如下代码上: -/Android/frameworks/base/services/ja

Android Service组件在进程内绑定(bindService)过程

本文参考Android应用程序绑定服务(bindService)的过程源代码分析http://blog.csdn.net/luoshengyang/article/details/6745181和<Android系统源代码情景分析>,作者罗升阳 一.Android Service组件在进程内绑定(bindService)过程 0.总图流程图如下: 1.Counter和CounterService所在应用程序主线程向ActivityManagerService进程发送BIND_SERVICE_T

android开发3:四大基本组件的介绍与生命周期

android开发3:四大基本组件的介绍与生命周期 Android四大基本组件分别是Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器,. 生命周期 是指进程周期 – 创建到结束的过程 进程类别 前台进程:当前正在前台运行的进程 可见进程:显示在前台中,但用户并未在和其进行交互 服务进程:为用户提供服务的进程 后台进程 空进程:该进程一般是为了缓存机制而存在的 组件介绍 Activity(表现层) 应用程序中,一个Act

Android开发-API指南-进程与线程

Processes and Threads 英文原文:http://developer.android.com/guide/components/processes-and-threads.html 采集(更新)日期:2014-12-25 搬迁自原博客:http://blog.sina.com.cn/s/blog_48d491300100zjpb.html 在本文中 进程 进程的生命周期 线程 工作线程 线程安全的方法 进程间通讯 如果某个应用程序组件是第一次被启动,且这时应用程序也没有其他组件

C#开发Linux守护进程

C#开发Linux守护进程 Linux守护进程是Linux的后台服务进程,相当于Windows服务,对于为Linux开发服务程序的朋友来说,Linux守护进程相关技术是必不可少的,因为这个技术不仅仅是为了开发守护进程,还可以拓展到多进程,父子进程文件描述符共享,父子进程通讯.控制等方面,是实现Linux大型服务的基础技术之一. 去年我也曾写了一篇关于守护进程的帖子,名字叫<.NET跨平台实践:用C#开发Linux守护进程>,这篇文章的的确确实现了一个Daemon,不过,它有一个弱点,不能运行多

开发指南专题十:JEECG微云快速开发平台--表单校验组件ValidForm

10.4Validform对象[方法支持链式调用] 如示例 var demo=$(".formsub").Validform(),那么demo对象会有以下属性和方法可以调用: tipmsg[object] 如:demo.tipmsg.s="error! no messageinputed."; 通过该对象可以修改除 tit 以外的其他提示文字,这样可以实现同一个页面的不同表单使用不同的提示文字. 具体可修改的提示文字 $.Tipmsg={//默认提示文字; tit:

【微信公众平台开发】借用微信内置图片浏览功能

开发微信公众平台时,碰到文章中有很多图片,需要可以点开图片浏览:那么点击图片直接调用微信客户端自带的图片播放组件会省很多事.否则你得去摆弄折腾各种图片浏览插件,比如photoswipe. 个人封装功能成一个js文件.把该文件放到你需要的网页里面即可,这样文章当你点击图片时,就会调用图片浏览功能! <script> function addLoadEvent(func){ //将函数作为参数,此函数就是 onload 触发时需要执行的某个函数 var oldonload=window.onloa

.NET跨平台实践:再谈用C#开发Linux守护进程

Linux守护进程是Linux的后台服务进程,相当于Windows服务,对于为Linux开发服务程序的朋友来说,Linux守护进程相关技术是必不可少的,因为这个技术不仅仅是为了开发守护进程,还可以拓展到多子进程,父子进程,父子进程通讯与控制等方面,是实现Linux大型服务的基础技术之一. 去年我也曾写了一篇关于守护进程的帖子,名字叫<.NET跨平台实践:用C#开发Linux守护进程>,这篇文章的的确确实现了一个Daemon,不过,它有一个弱点,不能运行多线程! 这篇帖子的目的就是进一步完善,让