com和dll,有什么区别?

oldsprite 2003-03-31 04:12:36
一段代码,封装成COM和封装成DLL,有什么区别?

调用起来又有什么不同呢?

封装COM,最后一定是*.tlb文件吗?

我看不出所谓的COM接口函数和DLL里封装的函数调用起来有什么区别?也不太清楚COM比DLL高明在哪里?
...全文
417 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
fhtao 2003-03-31
  • 打赏
  • 举报
回复
Com是一种通讯机制,可以做成dll或者exe得形式
所以COM不等于DLL,Dll也不是COM
wanneng882 2003-03-31
  • 打赏
  • 举报
回复
首先比较一下普通DLL与COM组件的优缺点:
1.函数名重名问题
Microsoft需要根据名称输出DLL的函数,而不是根据顺序值。当应用程序使用DLL
时,应用程序必须使用绝对唯一的名称来标识需要调用的 DLL函数。所以DLL总是有可能包含名称与其他DLL中的函数名称相同的函数。
2.各个编译器对C++函数的名称修饰不兼容问题
对于C++的类成员函数,编译器要通过使用基于函数参数的额外字母数字字符对函数名
称进行修饰,比如对void Foo(int i)变成:?Foo@@YAXH@Z。但是,函数修饰在C++编译
器中并不是统一的,所以采用VC建立的DLL 所输出的C++函数,不能在BC下使用。可
以通过定义 extern "C",可以关闭C++的DLL输出函数修饰,从而使函数具有标准C语言
函数的特征,从而可以被不同编译器兼容,但显而易见,失去了C++的特性,比如重载和多
态性。
3.路径问题
不论怎样,必须指明DLL的路径。
如果把DLL放到应用程序目录下,就不能让别的程序找到;如果把DLL放到系统目录
下,则会存在相同文件名冲突的危险。真正的组件应该可以放在任何地方,甚至不在本机上,
COM满足了这个要求。
4.DLL与EXE的依赖问题
一般我们采用隐式连接的方式,因为很简单。若采用这种方式,函数在DLL 被装载时
被固定。所以当重建DLL时,不能简单地把DLL新版本替换旧版本而不需重新编译。因为
DLL中各函数的地址可能已经发生了改变。
普通DLL的缺点就是COM组件的长处,它们虽然同为DLL,但差别是方法的差别,
是本质的。
经过采用比较我们最终将采用DLL的组件形式。采用ATL编写COM服务器。
启动接口为:HRESULT initalize();
我们的项目需要用到很多的对话框界面,是够应该考虑使用EXE的COM服务器,并且使用MFC建立COM服务器。
师兄写的调用ATL编写的DLL形式的COM服务器的代码:
if( FAILED( ::CoInitialize(NULL) ) ) //初始化COM
return;
LPUNKNOWN pUnk = NULL;
HRESULT hr = ::CoCreateInstance ( CLSID_ISPL,NULL,CLSCTX_INPROC_SERVER,IID_IUnknown,(void **)&pUnk );
if( SUCCEEDED( hr ) && pUnk != NULL )
{
IISPL * pSpl = NULL;
hr = pUnk->QueryInterface ( IID_IISPL,(void **)&pSpl );
if (SUCCEEDED( hr ) && pSpl != NULL)
{
long Result;
pSpl->Plus (1,2,&Result);
CString str;
str.Format (_T("%d"),Result);
AfxMessageBox( str );
pSpl->init( );
pSpl->Release ();
}
//////////
pUnk->Release ();
}
::CoUninitialize (); //一定记得需要卸载COM

使用MFC和ATL实现COM接口的方式是不同的MFC是使用嵌套类来实现COM接口,而另一种是使用(多)继承的方法实现一个(或多个)COM接口。
曾经的猎狐 2003-03-31
  • 打赏
  • 举报
回复
COM原理与应用
1、 从学COM难说起,以及学习COM时应该注意的事项。(认可方式,命名规则)
2、 COM是什么,COM可以干什么(COM的必要性)
a) Fortran与TC的混合编程的问题出发得出COM的二进制兼容特性。VB与VC程序员之间共存(取其长补其短)
b) 将一个大的程序分成多个功能模块实现一个功能独立的实体满足部分升级功能。
c) 在平时的工作中将有些功能相同的东西保存起来以后作为一个工具来使用,而且还要在多个平台下访问方便。
d) 从Office提供的二次开发功能说起,为其它人的使用提供一个二次开发的工具与手段。
e) 随着互联网的广泛应用对分布式应用提出了具体的需求(分布式运行、安全性控制、可伸缩性要求)
3、 C++复习之一(抽象类的继承(虚函数))(总结一句话:用基类的指针访问了子类的函数)
Class Animal,Class Person,Class Elephent
4、 C++复习之二(虚函数+多重继承)
Class Person,Class Scientist,Class Student,CA
5、 将类换成Struct更而将Struct换成Interface,从而引出接口的概念。
6、 提出COM原理三部分内容(访问特性、生存周期控件、对象创建(类厂))
7、 引出所有的COM对象都要从Iunknown接口继承。
实现QueryInterface接口方法(讲接口ID)
实现callCreateInstance函数
IUnknown* CallCreateInstance()
{
IUnknown* pIUn=(IUnknown*)(IStudent*)(new CA);
return pIUn;
}
(这里一定要调用一次AddRef)
8、 从C++的内存分配与管理入手比较COM的生存周期控制技术,实现AddRef与Release。
9、 客户机与服务器程序的概念。
10、 将代码分离到一个DLL中(只引出一个函数callCreateInstance)(最后要得出结论此时还不是COM)。
typedef IUnknown*(*fun)();
fun fun1;
HMODULE hModule=::LoadLibrary("SrvDll.dll");
fun1=(fun)::GetProcAddress(hModule,"CallCreateInstance");
IUnknown* pIUn=fun1();
11、 从编写客户端代码时LoadLibrary()函数中需要DLL文件的路径开始分析注册表项的需求。(DllRegisterServer与DllUnRegisterServer函数的作用)
12、 从安全性的考虑入手,以及与VC中的勾子的处理原理来引出类厂的概念。(一个对象一个类厂)
13、 类厂本身就是一个COM对象,那类厂又是由谁来创建的呢?由此引入DllGetClassObject()函数。从而引出一个对象需要一个GUID在此叫ClassID
14、 总结DLL作为载体时需要的引出函数(DLLGetClassObject、DLLRegisterServer、DLLUnRegisterServer…..)。
15、 从创建对象过程太复杂得出可以采用CoCreateInstance函数来完成这些功能。
16、 用到COM库就要对COM库进行初始化。(CoInitialize(NULL)与CoUnInitialize())

附类厂的实现代码
class CAClassFactory:public IClassFactory
{
public:
long count;
CAClassFactory()
{
count=0;
};

HRESULT _stdcall QueryInterface(REFIID iid,void ** ppvObject);
ULONG _stdcall AddRef();
ULONG _stdcall Release();

HRESULT _stdcall CreateInstance(IUnknown * pUnkOuter,REFIID riid,void ** ppvObject);
HRESULT _stdcall LockServer(BOOL fLock);
};

HRESULT CAClassFactory::QueryInterface(REFIID iid,void** ppvObject)
{
if(iid==IID_IClassFactory)
*ppvObject=(IClassFactory*)this;
else if(iid==IID_IUnknown)
*ppvObject=(IUnknown*)this;
count++;
return S_OK;
}
ULONG CAClassFactory::AddRef()
{
return count++;
}
ULONG CAClassFactory::Release()
{
if(--count==0)
{
delete this;
return 0;
}
else
return count;
}
HRESULT CAClassFactory::CreateInstance(IUnknown* pUnkOuter,REFIID riid,void** ppvObject)
{
CA* pCa=new CA;
pCa->QueryInterface(riid,ppvObject);
return S_OK;
}

HRESULT CAClassFactory::LockServer(BOOL fLock)
{
return S_OK;
}
STDAPI DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID * ppv)
{
if(rclsid==CLSID_A)
{
CAClassFactory* pCAClass=new CAClassFactory;
pCAClass->CreateInstance(NULL,riid,(void**)ppv);
}
return 0;
}

seaiam 2003-03-31
  • 打赏
  • 举报
回复
COM最后也可生成DLL
COM得先写进注册表,普通的DLL直接调用接口函数即可
guoxiny 2003-03-31
  • 打赏
  • 举报
回复
在地层来说,都一样,都是用LoadLibrary()函数调用的。但com的路径是通过注册表中的定义来查找的,而dll则是根据系统、本地路径来查找的。com还有很多其他方面的技术。

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧