分布式实验报告张莹127129Word文档下载推荐.docx
《分布式实验报告张莹127129Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《分布式实验报告张莹127129Word文档下载推荐.docx(40页珍藏版)》请在冰豆网上搜索。
![分布式实验报告张莹127129Word文档下载推荐.docx](https://file1.bdocx.com/fileroot1/2023-2/2/43e34bd5-904c-492c-922b-40cd02b1bcee/43e34bd5-904c-492c-922b-40cd02b1bcee1.gif)
13.接口类进行改造,以纯虚函数的方式提供释放对象的功能。
14.验证接口类不变时,实现类可以进行任意的更新,而客户端可以无缝升级。
15.验证接口类的变化带来升级的困难。
16.使用多接口的方式对对象进行扩展,验证在同种编译器的客户端可以顺利升级。
17.验证以上情形在异种客户端无法链接。
18.以功能函数的方式编译器中性地实现接口转换,验证异种编译器方式下也可顺利升级。
19.验证一个对象的多个接口之间的紧密耦合性。
20.以引用计数的方式消除多接口的紧密耦合性。
软件下载
虚拟光驱
C++builder
vs2012
实验过程
1、打开visualstudio,选择visualC++开发设置。
然后点击“启动”。
使用vc建立一个dllFastStringDll
●Win32,名称为FastStringDll
●Win32控制台应用程序
●DLL
●导出符号。
运行一下,可以成功。
添加类FastString
●右键点击项目
●添加
●类
●C++类
●输入类名FastString
●完成
输入代码
代码如下
产生头文件:
FastString.h
class__declspec(dllexport)FastString
{char*m_psz;
public:
FastString(char*psz);
~FastString(void);
intLength(void);
intFind(char*psz);
};
新增实现文件:
FastString.cpp
#include"
stdafx.h"
//预编译
FastString.h"
#include<
string.h>
FastString:
:
FastString(char*psz)
m_psz(newchar[strlen(psz)+1])
{strcpy_s(m_psz,strlen(psz)+1,psz);
}//分配内存
~FastString(void)
{delete[]m_psz;
}//释放内存
intFastString:
Length(void){
returnstrlen(m_psz);
}//计算长度
Find(char*psz)
{return0;
}//省略,这不是我们讨论的重点.
选择release,再运行一下。
这时就生成了dll文件
2、在解决方案下添加一个客户端,使用vc客户端调用此类
●建立vc控制台程序VCClient
●设定项目属性-》配置属性:
●C/C++-》常规:
附加包含目录:
编辑:
新行:
$(SolutionDir)\FastStringDll这里路径要引对,要引入dll文件。
D:
\com\FastStringDll\Release
\com\FastStringDll\FastStringDll
●链接器-》常规:
附加库目录:
$(SolutionDir)$(Configuration)\
●链接器-》输入:
附加依赖项:
编辑加入:
FastStringDll.lib
●代码VCClient.cpp
#include<
iostream>
usingnamespacestd;
int_tmain(intargc,_TCHAR*argv[])
{
FastString*pFS=newFastString("
fdfd"
);
intres=pFS->
Length();
cout<
<
res<
endl;
return0;
}
●设定VCClient为启动项目
运行成功。
3.使用BC创建一个客户端BCClient
●打开bc创建一个VCLFormsApplication应用程序。
●在VC的解决方案文件夹下新建文件夹筛选器BCClient。
●在BCClient内对BC项目全部保存起来,再导入到VCClient里面
●在BC窗口界面点一下button,再点一下视图,就能添加一个按钮了。
这里产生点击click处理事件。
●在Unit1.cpp中,#include"
Unit1.h"
后面加入#include"
●运行,发现[bcc32Error]Unit1.cpp(7):
E2209Unabletoopenincludefile'
FastString.h'
●设定包含路径:
Project-》Options–》C++Compiler–》Directories&
conditional
includefilesearchpath加上../FastStringDll
VS2012是在属性-》配置属性-》VC++目录-》包含目录
●编译通过
●加入代码:
:
FastString*pFS=newFastString("
●对于以上代码提示无法链接
[ilink32Error]Error:
Unresolvedexternal'
FastString(char*)'
referencedfromD:
\TEST\FASTSTRINGDLL\BCCLIENT\WIN32\DEBUG\UNIT1.OBJ
●View–》ProjectManager添加FastString.lib文件
链接失败提示:
无效的OMF,PossibleCOFF.
'
\TEST\FASTSTRINGDLL\DEBUG\FASTSTRINGDLL.LIB'
containsinvalidOMFrecord,type0x21(possiblyCOFF)
这里是因为跨平台,所以vc下引用dll和bc下引用效果不一样。
所以如何解决这个问题呢?
●使用coff2omf工具,cmd中输入“coff2omf.exeFastStringDll.libbc.lib”进行转换。
需要先退出C盘,进入D盘lib文件所在的地方
到上一级目录,请使用cd..
进入D盘,请使用d:
进入想要的目录,请使用cd
这里还有其他两种方法
一、使用implib命令
1、用C++Builder的implib工具生成DLL对应的lib文件。
生成lib文件之后,C++Builder便可以使用这个lib文件了。
2、在.h中用extern"
C"
修饰VC导出的DLL函数。
如:
extern"
__declspec(dllexport)intaFunc(inta),就可以调用了。
二、coff2omf.exe
工具程序coff2omf.exe将.lib转换为BCB可用的,然后添加进工程,直接使用VC的头文件就可以了。
三、动态调用
C/C++code
//Main.h
HINSTANCEhDllInst;
//声明Dll句柄
int(__stdcall*sdfm)(unsignedchar,unsignedshort,long);
//声明变量
//Main.cpp
void__fastcallTForm:
FormCreate(TObject*Sender)
{//框架启动时初始化Dll模块,这里以DllName.dll为例
if(NULL==hDllInst)
hDllInst=LoadLibrary("
DllName.dll"
if(hDllInst)
sdfm=(int(__stdcall*)(unsignedchar,unsignedshort,long))GetProcAddress(hDllInst,"
sdfm"
}
生成的新lib文件如图:
●把bc.lib包含到项目中
●提示构造函数无法链接。
4.在VC中,FastString输出函数CreateObject:
FastString.h文件:
extern"
__declspec(dllexport)FastString*CreateObject(char*psz);
FastString.cpp文件:
FastString*CreateObject(char*psz)
{
returnnewFastString(psz);
}
●重新编译,重新更新lib文件。
●BCClient:
代码改为:
FastString*pFS=CreateObject("
fdfdd"
●编译通过!
●但是如果加上:
pFS->
Length();
//提示链接出错。
5.把Length和Find改为虚函数。
以上链接通过。
6.BC的运行过程。
●IDE下运行无结果。
●直接运行提示出错:
找不到DLL
●Project–》options-》C++(SharedOptions)->
将Finaloutput设定为Dll所在位置:
../Debug
●代码:
ffdfd"
intlen=pFS->
Length();
ShowMessage(AnsiString(len));
7.Length或者Find的执行情况:
执行结果不正确,将其改为_stdcall执行结果正常
8.此时可以取消对类的输出。
即服务器端删除掉__declspec(dllexport)
Bc客户仍可正常执行。
9.对数据的敏感性:
客户编译器与服务器编译器同时依赖于同一个c++类定义,
在类的定义部分:
加上:
Public:
inta;
intb;
构造函数中:
a=2;
b=5;
以此文件生成dll,
客户端输出:
ShowMessage(AnsiString(pFS->
a));
ShowMessage(AnsiString(pFS->
b));
以此文件生成客户。
得到版本1.
改变a,b的定义顺序。
生成dll和客户。
得到版本2.
打乱客户和dll的搭配关系。
A和b的值都将颠倒。
实际上是一个显示的交叉转换过程。
10.于函数也有如上特性对虚拟函数的敏感性:
定义两个虚函数:
virtualintfa();
virtualintfb();
分别实现之。
编译服务器端和客户端。
改变定义顺序:
virtualintfa();
编译服务器端和客户端。
打乱版本的搭配顺序,调用将出现错乱。
11.对普通函数的不敏感性:
这里客户要用同种编译器,即vc
对于以上的虚函数,改为非虚的。
打乱次序后,调用不会出错。
说明是通过名字解析的方式进行的。
12.所以要对接口进行抽象。
降低耦合性。
添加接口类:
IFastString
头文件:
classIFastString
{
public:
virtualint_stdcallLength(void)=0;
virtualint_stdcallFind(char*psz)=0;
~IFastString();
IFastString();
};
实现文件:
IFastString.h"
IFastString:
IFastString(void)
~IFastString(void)
实现类FastString.h中:
classFastString:
publicIFastString
……
CreateObject的返回值改为IFastString
其声明:
__declspec(dllexport)IFastString*CreateObject(char*psz);
放到接口头文件中。
客户端代码改为:
IFastString*pFS=CreateObject("
fddfd"
13.因为接口中已经没有数据,所以自然不存在数据的敏感性。
14.在vc客户端,使用delete进行内存释放:
验证普通析构函数会出现内存泄漏。
验证方法:
⏹接口类重新向外输出__declspec(dllexport)
⏹子类分配大量内存。
IFastString*pFS=CreateObject("
deletepFS;
boolb=_CrtDumpMemoryLeaks();
//监控函数
b<
⏹b为1,表示有泄漏。
⏹或者使用windows任务管理器等监控机构。
15.对以上使用虚析构函数,代码为:
classIFastString
IFastString(void);
virtual~IFastString(void);
virtualint__stdcallLength(void)=0;
//返回该字符串的长度
virtualint__stdcallFind(char*psz)=0;
//查找指定的子串
注意此时既然使用虚析构,则不用输出接口类了。
验证vc客户端内存泄漏消失。
16.验证在bc客户端,仍然对析构函数链接失败。
intlen=pFS->
deletepFS;
析构函数位置不同而产生链接失败。
17.接口改为如下形式:
●取消输出
●增加Delete虚函数。
●采用默认的构造和析构函数。
virtualvoid_stdcallDelete()=0;
delete的实现:
voidFastString:
Delete()
deletethis;
}
18.BC客户端改为:
IFastString*pIFS=CreateObject("
intres=pIFS->
ShowMessage(AnsiString(res));
pIFS->
Delete();
通过。
19.对接口进行改变
virtualint_stdcallFindN(char*psz,intn)=0;
FastString实现新函数。
客户端对其进行调用。
生成版本2.
打乱版本1和2搭配次序。
●老客户用新对象,正常。
●新客户用老对象,失败。
20.增加新的接口:
classIPO
virtualvoid_stdcallDelete()=0;
virtualvoid_stdcallSave()=0;
多重继承:
classFastString:
publicIFastString,publicIPO
客户端:
IPO*pIPO=dynamic_cast<
IPO*>
(pIFS);
验证
●VC在接口之间可以正常运行。
IFastString*pIFS=CreateObject("
intres=pIFS->
IPO*pIPO=dynamic_cast<
pIPO->
Save();
deletepIFS;
●BC客户端运行异常
21.中性的类型转换
接口改为如下形式:
增加dynamic函数。
classIEO
virtualvoid_stdcallDynamic(char*name,void**ppI)=0;
classIFastString:
publicIEO
classIPO:
publicIFastString,publicIPO
实现方式:
voidFastString:
Dynamic(char*name,void**ppI)
if(strcmp(name,"
IFastString"
)==0)
*ppI=(IFastString*)this;
elseif(strcmp(name,"
IPO"
*ppI=(IPO*)this;
IEO"
调用方式:
IPO*pIPO;
IEO*pIEO;
Dynamic("
(void**)&
pIPO);
pIPO->
pIEO);
22.验证多接口之间的紧密耦合性。
略。
23.引用计数。
改写接口,为以上对象添加引用计数功能
实验心得
上机课有些手忙脚乱,安装软件时也遇到各种未知问题……但一切都井然有序地进行着。
做实验最大的难题,是需要先弄懂一个关键,WHY——为什么我们要做这个实验,即这个实验的目的是什么。
弄通目标之后,接下来的实验就进行得轻松愉快了。
最重要的一句话“因为跨平台,所以VC和BC下引用DLL的效果可能不一样。
”
XX,也让我们的实验显得容易很多。
善于使用搜索引擎也是益处多多的。
比如搜索一下“C++Builder的开发指南”,就会发现很多跨平台的例子。
这个会大大帮助我们理解实验,使实验顺利地进行下去。
实验报告毕竟是份文档,如果能把实验者自己的想法、截图的方式和报告的书写,沉淀为更加规范的格式,那想必是份完美的文档。
分布式不是一门很好理解的课程,但老师能从上课、完美翻译的参考书、实验、作业等一系列方式让我们多方位地理解这门课,我们是受益匪浅的。
最后,感谢老师辛苦的授课!