求助:delphi写的com组件的返回值如果是hresult,应该怎么办?(100分)

  • 主题发起人 主题发起人 djjsl
  • 开始时间 开始时间
D

djjsl

Unregistered / Unconfirmed
GUEST, unregistred user!
在下有一个函数post,有四个参数要输入,一个返回值,在下想通过atl和dephi实现,
vc的idl如下:
interface ITeleNote : IDispatch {
[id(0x00000001), helpstring("method Post")]
HRESULT Post(
[in] BSTR phonenumber,
[in] BSTR message,
[in] short billtype,
[in] BSTR billphone,
[out, retval] short* result);
测试成功。然后,在下接着实现delphi的,我选了activex library + com,定义方法post
如下:
interface ITeleNote : IUnknown {
HRESULT _stdcall Post(
[in] BSTR phonenumber,
[in] BSTR message,
[in] short billtype,
[in] BSTR billphone,
[out, retval] short* rst);
现在,问题来了,post的最后一个参数rst在程序中声明总是这样:
function Post(const phonenumber, message: WideString; billtype: Smallint;
const billphone: WideString; out rst: Smallint): HResult; stdcall;
如上,rst总是一个out型,而不是out,retval型。

我接着作了两个delphi的客户端测试程序,分别对atl和delphi的组件进行测试,导入了
他们的lib文件,发现atl的post函数是如下:
function TTeleNote.Post(const phonenumber: WideString; const message: WideString;
billtype: Smallint; const billphone: WideString): Smallint;
begin
Result := DefaultInterface.Post(phonenumber, message, billtype, billphone);
end;
而delphi的确是如下:
function TTeleNote.Post(const phonenumber: WideString; const message: WideString;
billtype: Smallint; const billphone: WideString; out rst: Smallint): HResult;
begin
DefaultInterface.Post(phonenumber, message, billtype, billphone, rst);
end;

请问,我在delphi编写com时该如何声明参数,才能使得情况和atl编的组件一样。
另外,还有个问题,atl的组件是实现了idispatch接口的,但在delphi中选择com,
只是实现了iunkown接口,我的组件需要在脚本或delphi,vc,vb中使用,在delphi
中该选择那个方式?
 
简单地说,通常COM对象的接口方法的返回值是HRESULT,它表
明了这个方法调用的成功与否,而你想要返回的数据是通过定义成[out,retval]。
你在VB里看到的是COM Runtime为你处理过了的,比如你的GetRS方法中如果出错,
GetRS的HRESULT将不为S_OK, 那么在VB中将会产生一个Exception(VB的Error)。
IDispatch是从IUnknown上继承下来,主要是给ASP等需要运行时Binding的语言用
的,因为这种情况下无法用基于vtbl的Binding,通过IDispatch的Invoke方法来调
用,等等......关于这个话题要讲的话可以写本书了,建议你去找本书看。总的来
说, MTS/COM+比J2EE学习起来要复杂一些, 但在Windows平台上MTS/COM+比J2EE
要快。
 
谢谢cwmdelpher,但你的回答没有解决我的问题。
按照我上面的声明方法,idl中不同的地方就在于delphi变成了HRESULT _stdcall,
但是在客户端的delphi程序中,atl的post声明和delphi的post声明就不一样了。
我想知道delphi该如何做才能和atl的一样。
另外想知道如何在delphi中实现idispatch接口.
 
很奇怪,如果在下在delphi中将返回值从hresult改为short,那么
在客户端导入的lib文件为:
function TTeleNote.Post(const phonenumber: WideString; const message: WideString;
billtype: Smallint; const billphone: WideString): Smallint;
begin
DefaultInterface.Post(phonenumber, message, billtype, billphone);
end;
这与atl那边的很像:
function TTeleNote.Post(const phonenumber: WideString; const message: WideString;
billtype: Smallint; const billphone: WideString): Smallint;
begin
Result := DefaultInterface.Post(phonenumber, message, billtype, billphone);
end;
比较一下,发现上面的没有result.
 
Delphi中的Com的返回值不是这样搞的
你新建一个参数xx,在参数类型后面加入*号,然后在Modifier中,Out打勾,RetVal打勾。
然后你在程序中把要返回的值赋给xx,就行了。
虽然函数的返回值依旧显示HRESULT,但调用的时候返回的确实是xx的值
 
pnljh,我的确是这样做的,兄台可以看看我上面的内容。
调用的时候返回的不是xx得值,而是这样的:(在客户端import library)
function TTeleNote.Post(const phonenumber: WideString; const message: WideString;
billtype: Smallint; const billphone: WideString; out rst: Smallint): HResult;
begin
DefaultInterface.Post(phonenumber, message, billtype, billphone, rst);
end;
看上面,rst本来是short*,结果却是out rst: Smallint。
而且DefaultInterface.Post(phonenumber, message, billtype, billphone, rst);,这根本就不对。
 
的确,rst算是输出参数,但问题是atl和delphi的idl定义基本相同,除了delphi在hresult
后加了一个stdcall之外。而在客户端的程序中,他们导入的lib却很不相同,一个是
function TTeleNote.Post(const phonenumber: WideString; const message: WideString;
billtype: Smallint; const billphone: WideString): Smallint;
begin
Result := DefaultInterface.Post(phonenumber, message, billtype, billphone);
end;
一个是:
function TTeleNote.Post(const phonenumber: WideString; const message: WideString;
billtype: Smallint; const billphone: WideString; out rst: Smallint): HResult;
begin
DefaultInterface.Post(phonenumber, message, billtype, billphone, rst);
end;

我猜想原因可能是因为atl实现的是idispatch接口的原因。cwmdelpher的回答很有道理,
但他没有完全回答我的问题。就是该如何才能实现idispatch接口。
 
解决了。
的确是因为idispatch和iunknown的原因。
谢谢大家!
 
多人接受答案了。
 
后退
顶部