晶
晶晶
Unregistered / Unconfirmed
GUEST, unregistred user!
现在流行写心得(中国的程序员就是要多点这种行为,好的东西大家共享嘛)!我也写了一篇
现在节选其中一部分,如果大家发现什么不对的地方或者有更好的见解记得告诉我啊!
如果要看全文,大家可以访问:http://202.101.234.106/bbs/list.asp?boardid=1里面有这篇
文章的全部!
追本朔源说COM-3
简单的利用开发向导,写几行简单的代码就完成一个显示时间的com服务器,是不是很简单,如果
你真的这么认为那你就错了。对!虽然你会用delphi开发com了,但如果你想理解它或者以后开发
复杂的com和深入dcom机制不理解它的运行机制是不可能的!现在我们先就调用端来分析一下它是
怎么工作的!
我们调用是用这样的形式:
map:=createcomobject(clsid_tmyclass) as imyinterface;
其实这里完成的是两个操作:
完整的应该是这样的:
map1:=createcomobject(clsid_tmyclass);//map1是一个iunknown类型的接口
map1.queryinteface(iid_shelllinka,map);//通过map1查找iid_shelllinka接口
仅靠系统提供一个createcomobject我们就可以使用一个com服务器了,这个函数
肯定做了什么?
在delphi的源代码中createcomobject是这样定义的:
function createcomobject(const classid: tguid): iunknown;
begin
olecheck(cocreateinstance(classid, nil, clsctx_inproc_server or
clsctx_local_server, iunknown, result));
end;
呵呵,原来是函数的包装啊!
这里就要介绍一下cocreateinstance函数。
function cocreateinstance;
external ole32 name 'cocreateinstance';
它是系统(ole32.dll)提供的一个api,那么它是做什么的呢,具体做了什么工作?
这个函数真正要我们提供的参数就是一个classid,其他的可以使用上面的默认值。
它会从注册表中找该com类的classid(在hkey_classes_root/clsid键中),找到相应
的键后系统会读取其中inprocserver32的数据,找到服务器的地址后用loadlibrary函
数将服务器dll载入宿主进程,再利用dll中的dllgetclassobject函数(这是每一个dll
形式com服务器必须提供的函数),获取了iclassfactory接口指针后利用这个接口中
createinstance方法创建我们需要的com对象的实例(这个时候对象才出现了)!好了,
现在知道他们之间的调用过程吗。小节一下:
createcomobject-->cocreateinstance-->注册表clsid-->loadlibrary
-->dllgetclassobject(我们在后面分析中将从这里开始)
-->iclassfactory.createinstance
好了,前面的分析完成了,由于它大部分功能都是由系统完成的,没有多少研究的必要,
你只要会用,知道怎么用和它是做什么的就可以了。(也没有条件分析下去,我可没有
这个api的源码,你只有去问微软了,不知道它会不会给你),那么下面我们从
dllgetclassobject函数开始分析,它是编程语言提供的(系统要求的,工具提供的),我
们可以分析其中的代码,先看看dll工程的代码:
library project3;
uses
comserv,
unit3 in 'unit3.pas',
project3_tlb in 'project3_tlb.pas',
unit7 in 'unit7.pas' {form1};
exports
dllgetclassobject,
dllcanunloadnow,
dllregisterserver,
dllunregisterserver;
{$r *.tlb}
{$r *.res}
begin
end.
仅仅是导出comserv库中的四个函数,其中dllgetclassobject我们上面说过,也是最重要
的,先分析它:
function dllgetclassobject(const clsid, iid: tguid;
var obj): hresult;
var
factory: tcomobjectfactory;//注意:这里都是由类工厂提供的。
begin
factory := comclassmanager.getfactoryfromclassid(clsid);//1
if factory <> nil then
if factory.getinterface(iid, obj) then
//2
{由类工厂去查找相应的iid,成功就返回s_ok,并且将接口指针返回给obj}
result := s_ok
else
result := e_nointerface{没有找到就返回e_nointerface}
else
begin
//如果没有相应类工厂
pointer(obj) := nil;//将接口指针置nil
result := class_e_classnotavailable;
end;
end;
现在讲讲这个函数,这个函数通过clsid, iid参数来找他们在dll中的接口的位置,然后
通过参数obj来返回指针,而整个函数的返回值(hresult类型)只是用来告诉系统接口是
否存在。这里的obj是什么呢?就是我们前面定义的map啊!是不是对于这种返回形式还不
适应,不要紧,看多了就知道了,这种返回形式很有效的!不过要注意到它是var声明形
式的哟!!这个函数要往下分析的部分(或者要重点注意的部分)已经用数字标明了!那
么我们下一节就先分析1吧。
好了,先讲到这里,下节见。
晶晶
现在节选其中一部分,如果大家发现什么不对的地方或者有更好的见解记得告诉我啊!
如果要看全文,大家可以访问:http://202.101.234.106/bbs/list.asp?boardid=1里面有这篇
文章的全部!
追本朔源说COM-3
简单的利用开发向导,写几行简单的代码就完成一个显示时间的com服务器,是不是很简单,如果
你真的这么认为那你就错了。对!虽然你会用delphi开发com了,但如果你想理解它或者以后开发
复杂的com和深入dcom机制不理解它的运行机制是不可能的!现在我们先就调用端来分析一下它是
怎么工作的!
我们调用是用这样的形式:
map:=createcomobject(clsid_tmyclass) as imyinterface;
其实这里完成的是两个操作:
完整的应该是这样的:
map1:=createcomobject(clsid_tmyclass);//map1是一个iunknown类型的接口
map1.queryinteface(iid_shelllinka,map);//通过map1查找iid_shelllinka接口
仅靠系统提供一个createcomobject我们就可以使用一个com服务器了,这个函数
肯定做了什么?
在delphi的源代码中createcomobject是这样定义的:
function createcomobject(const classid: tguid): iunknown;
begin
olecheck(cocreateinstance(classid, nil, clsctx_inproc_server or
clsctx_local_server, iunknown, result));
end;
呵呵,原来是函数的包装啊!
这里就要介绍一下cocreateinstance函数。
function cocreateinstance;
external ole32 name 'cocreateinstance';
它是系统(ole32.dll)提供的一个api,那么它是做什么的呢,具体做了什么工作?
这个函数真正要我们提供的参数就是一个classid,其他的可以使用上面的默认值。
它会从注册表中找该com类的classid(在hkey_classes_root/clsid键中),找到相应
的键后系统会读取其中inprocserver32的数据,找到服务器的地址后用loadlibrary函
数将服务器dll载入宿主进程,再利用dll中的dllgetclassobject函数(这是每一个dll
形式com服务器必须提供的函数),获取了iclassfactory接口指针后利用这个接口中
createinstance方法创建我们需要的com对象的实例(这个时候对象才出现了)!好了,
现在知道他们之间的调用过程吗。小节一下:
createcomobject-->cocreateinstance-->注册表clsid-->loadlibrary
-->dllgetclassobject(我们在后面分析中将从这里开始)
-->iclassfactory.createinstance
好了,前面的分析完成了,由于它大部分功能都是由系统完成的,没有多少研究的必要,
你只要会用,知道怎么用和它是做什么的就可以了。(也没有条件分析下去,我可没有
这个api的源码,你只有去问微软了,不知道它会不会给你),那么下面我们从
dllgetclassobject函数开始分析,它是编程语言提供的(系统要求的,工具提供的),我
们可以分析其中的代码,先看看dll工程的代码:
library project3;
uses
comserv,
unit3 in 'unit3.pas',
project3_tlb in 'project3_tlb.pas',
unit7 in 'unit7.pas' {form1};
exports
dllgetclassobject,
dllcanunloadnow,
dllregisterserver,
dllunregisterserver;
{$r *.tlb}
{$r *.res}
begin
end.
仅仅是导出comserv库中的四个函数,其中dllgetclassobject我们上面说过,也是最重要
的,先分析它:
function dllgetclassobject(const clsid, iid: tguid;
var obj): hresult;
var
factory: tcomobjectfactory;//注意:这里都是由类工厂提供的。
begin
factory := comclassmanager.getfactoryfromclassid(clsid);//1
if factory <> nil then
if factory.getinterface(iid, obj) then
//2
{由类工厂去查找相应的iid,成功就返回s_ok,并且将接口指针返回给obj}
result := s_ok
else
result := e_nointerface{没有找到就返回e_nointerface}
else
begin
//如果没有相应类工厂
pointer(obj) := nil;//将接口指针置nil
result := class_e_classnotavailable;
end;
end;
现在讲讲这个函数,这个函数通过clsid, iid参数来找他们在dll中的接口的位置,然后
通过参数obj来返回指针,而整个函数的返回值(hresult类型)只是用来告诉系统接口是
否存在。这里的obj是什么呢?就是我们前面定义的map啊!是不是对于这种返回形式还不
适应,不要紧,看多了就知道了,这种返回形式很有效的!不过要注意到它是var声明形
式的哟!!这个函数要往下分析的部分(或者要重点注意的部分)已经用数字标明了!那
么我们下一节就先分析1吧。
好了,先讲到这里,下节见。
晶晶