为在用COM做程序的DELPHI程序员提个醒 -- FROM FOXNT

foxnt 2003-07-30 04:13:28
我看到很多初学者(可能是受了某人的书的影响),在用COM写程序的时候,在传递一些TYPELIB编辑器未定义的类型作为参数时,总是喜欢使用VARIANT来作为参数。这个虽然没什么错误,但是是个不好的习惯。

VARIANT这种类型本身占用内存大,速度慢。而且只支持标准类型,很难支持自定义的参数类型。所以大家如果有自定义的参数类型要传递给COM方法时,建议大家使用如下方式:
1)使用自定义的interface,该interface当然是从Iunknown或者IDispatch继承下来的。为他们定义自己的属性,然后作为参数传递,就可以达到目的。例如:

HRESULT _stdcall SendPacket([in] IPacket * pPacket);

该例子用一个自定义的IPacket接口作为参数来传递。
IPacket = interface(IUnknown)
['{678F2D1B-5D36-4AB8-AB35-DA09788D3150}']
function Clear: HResult; stdcall;
function Get_Length(out pVal: Integer): HResult; stdcall;
end;

特别的。以前在DELPHI里有个经典的问题,很多人都问,怎么在COM里传出一个ado的Recordset出来。当时很多人都发现无法使用VARIANT来传这个东西。但是其实很简单,用一个IUnknown类型就可以传出来了。因为Recordset就是一个接口类型。:)

2)如果你不想使用接口,想使用完全自定义的类型,比如你自己定义的一个指针对象。可以使用void*这种方式(注意这种方式不能在DCOM里使用)
HRESULT _stdcall AddData([in] void * pDataAddRess, [in] long Len );

delphi把void*解析成pointer这种无类型指针。注意,大家可以查看下编辑器生成的IDL代码,其实DELPHI是省略了[local]表示符。MS定义的标准方式其实应该是:

[local][helpstring("method GetData")] HRESULT GetData([out,retval] void* pDataAddRess);

前面有个[local]符号,表示这是本地调用。

希望对大家有用。赶快抛弃没用的VARIANT吧。
...全文
48 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
myling 2003-08-04
  • 打赏
  • 举报
回复
老大,请教一下


我曾经做过个试验,在各种方式下传各种类型(除了接口),结果根本看不出有什么时间上的差别,我的表是3万条纪录,10几个字段,会不会是太小了?


请老大明示
tw_cshn 2003-08-04
  • 打赏
  • 举报
回复
GOOD
TOMWLD 2003-08-04
  • 打赏
  • 举报
回复
thanks
Volker 2003-08-04
  • 打赏
  • 举报
回复
学习...
pandengzhe 2003-08-04
  • 打赏
  • 举报
回复
up!
PhilexPei 2003-08-04
  • 打赏
  • 举报
回复
顶,畅所欲言啊
eastliangliang 2003-08-04
  • 打赏
  • 举报
回复
是啊,对于ASP调用来说,除了OleVariant,它还真不认其它类型。
halfdream 2003-08-04
  • 打赏
  • 举报
回复




有不同看法:
1,关于效率.离开特定环境,具体项目谈效率只是空对空的。要跟踪实现运行情况,
拿数据说话。特别在具体项目中,涉及因素太多,此消彼长,不能一概而论。。
2,关于variant的使用,则见仁见智。
至少它是调用间弱化类型的一个重要工具,在一个大型的,复杂的系统中,
仅拿软件来说,就有’硬‘有’软‘,有些部分需要做成硬硬的组件,有些适宜写
成脚本,运行时候随时就改。。变体类型,也就是Variant型在里面功劳不小。

beginer001 2003-08-03
  • 打赏
  • 举报
回复
s
pibpib2001 2003-08-03
  • 打赏
  • 举报
回复
学习
autumnlj 2003-08-01
  • 打赏
  • 举报
回复
学习
猛禽 2003-08-01
  • 打赏
  • 举报
回复
什么事情都不是绝对的,基本上VARIANT和接口的区别有点类似于C中void *和typed *的区别,void *不推荐使用,不表示它完全不能用,要看具体情况。
foxnt 2003-07-31
  • 打赏
  • 举报
回复
不好意思,上面的连接给错了。:) 不过那篇也是篇好文章。

《设计数据层组件并在层间传递数据》
http://www.microsoft.com/china/msdn/library/dnbda/html/BOAGag.asp
foxnt 2003-07-31
  • 打赏
  • 举报
回复
不对。有状态和无状态的区别不是由是否是VARIANT来决定的。VARIANT一样也有可能是有状态的,指针对象一样可以是无状态的。一般来说,作为面向对象设计方式,直接返回RecordSet在自己的业务逻辑里,是不被赞成的。MS有一套固定的开发模型,我不知道你研究过没有。可以用来解决这个问题。

》》你必须在客户端和组件中同时维护这个对象。
你这句话我没看懂您的意思。一般来说,无论是否对象,只要是块内存区,谁产生它的,就由谁来释放。而不存在两端都要维护的可能性。

如何设计数据集对象,已经超出本贴的范围。如果你有兴趣,可以另外开贴讨论。:)
我建议您可以看看这篇文章(MS推荐必看)

《业务对象映射到关系数据库的若干模式》
http://www.oone.com.cn/article/oorpat.htm
PhilexPei 2003-07-31
  • 打赏
  • 举报
回复
面向对象我是新手,既然提出来了,就把它讨论到底。
PhilexPei 2003-07-31
  • 打赏
  • 举报
回复
一般来讲我都是使用远程数据模块,现在接手的一个项目也是第一次考虑直接使用com技术,是个c/s模式的软件。因为要考虑到升级的问题。

虽然我们设计呢也是采用的oo的方法,但如何看待和处理数据集是我一直头痛的问题。

你通过对象传递的方法,无非是传递了一个指针,你能够处理这个对象的前提是,你必须在客户端和组件中同时维护这个对象。试问我是维护一个无状态的variant好还是维护一个有状态的对象好呢?我本来只是传一个数据,现在变成维护一个对象。


FrameSniper 2003-07-31
  • 打赏
  • 举报
回复
学习...........只能学习..............
citytramper 2003-07-31
  • 打赏
  • 举报
回复
占位
foxnt 2003-07-31
  • 打赏
  • 举报
回复
1)通过接口传递是COM的标准做法
2)任何传递数据当然是要有开销的,我的意思是用接口传递会比用VARIANT效率高。答案看我上面的回答。
3)我不知道你们到底是怎么写程序的?一般来说,一个合格的面向对象的程序员,会在系统中包装很多自己定义的接口对象。比如我要传递一个货物的数据集,我就会定义这个货物为一个对象,包含他所有的属性,然后作为接口传递。
TSomething = class(TMyParent, ISomething)
.....
end;
然后在传递参数时作为接口ISomething 传递给COM接口方法。peiweiwei你上面那样问,给我的感觉就是你在写程序时完全没有自定义对象,你的程序不是面向对象的。所以才会那样问。:)
foxnt 2003-07-31
  • 打赏
  • 举报
回复
veryok: 我想你可以看看WINDOWS定义的VARIANT到底是个什么样的类型,你就会了解到效率上的差别。要知道,查看效率不能凭人的感觉来做的。:)另外VARIANT也不是什么后期编译的需要,他只是在运行时自动转换成相应的类型。只是DELPHI把这些都屏蔽了,你看不到而已。
另外没有必要因为MIDAS用了VARIANT,你也跟风。MIDAS用它是为了使MIDAS比较通用,方便一些人使用而已。而并不是说VARIANT很好。

我要说的就这么多。是是非非大家自己判断。我只根据我的经验给大家提醒而已。:)
加载更多回复(13)

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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