远程数据模块中添加的接口方法应当用 safecall 还是 stdcall 调用方式?

hiflower 2003-09-16 10:28:25
Win2000+D6, MIDAS

在远程数据模块的接口中添加了一个 Login 方法,默认为 safecall 调用方式。
客户端用 SocketConnection1.AppServer.Login( ) 调用时,抛出“无效的方法调用”异常。
后来在 XXX_TLB.pas 中把 safecall 改为 stdcall,就可以正常调用了。

为什么 safecall 不行呢?按帮助应当是用 safecall 的啊!

The safecall convention must be used for declaring dual-interface methods

A dual interface is an interface that supports both compile-time binding and runtime binding through Automation. Dual interfaces must descend from IDispatch.
All methods of a dual interface (except from those inherited from IInterface and IDispatch) must use the safecall convention, and all method parameter and result types must be automatable. (The automatable types are Byte, Currency, Real, Double, Real48, Integer, Single, Smallint, AnsiString, ShortString, TDateTime, Variant, OleVariant, and WordBool.)
...全文
138 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
猛禽 2003-09-18
  • 打赏
  • 举报
回复
原来如此,真是想不到花兄居然会犯这种错误:)

SafeCall的异常是通过HResult传递的,而且如果是Automation,不用HResult还会有很多问题的。
qiume 2003-09-18
  • 打赏
  • 举报
回复
听课
hiflower 2003-09-18
  • 打赏
  • 举报
回复
请大家再帮我看一看这个问题: 三层中的回调问题
http://expert.csdn.net/Expert/topic/2272/2272375.xml?temp=.5014154
huojiehai 2003-09-17
  • 打赏
  • 举报
回复
我们一直用的都是safecall,可能与你的环境有关,具体也不大清楚!
hiflower 2003-09-17
  • 打赏
  • 举报
回复
诸位,我终于找到原因了。
我犯了个错误,类型库编辑器 的 Parameters 面板中,Return type 只能设置为 HResult,并用 RetVal 参数作为返回值,才能通过 safecall 正确调用。

还发现,当 Return type 设置为其它类型时,点击 Save 后,弹出消息框说:
Functions of Automation Interfaces must have a return type of HRESULT.
如果先点 Compile 进行编译,再点 Save,则无此警告,但运行后出现我上面所提出的错误现象。丢失警告,这可能是 Delphi 的一个 BUG 了。
猛禽 2003-09-17
  • 打赏
  • 举报
回复
呵,花兄如此高人也会碰上问题啊。:)

流铭所言极是,花兄可以一试。

特别是他的方法2,可以确定问题出在哪一端
DWGZ 2003-09-17
  • 打赏
  • 举报
回复
safecall与stdcall的相同之处是它们都是将参数按相反的顺序入栈,
不同之处是safecall如果产生了异常会把产生的异常又传递给给使用者, 而stdcall不会
你所说的用stdcall可以正常使用是指什么呢?是不抛出异常还是程序可以正确执行?
DWGZ 2003-09-17
  • 打赏
  • 举报
回复
safecall与stdcall的相同之处是它们都是将参数按相反的顺序入栈,
不同之处是safecall如果产生了异常会把产生的异常又传递给给使用者, 而stdcall不会
你所说的用stdcall可以正常使用是指什么呢?是不抛出异常还是程序可以正确执行?
leapmars 2003-09-17
  • 打赏
  • 举报
回复
一般来说,出现这种情况极有可能是你的代码中存在问题,因为用 SocketConnection 来进行调用一般不存在配置上的问题(当然要检查你的防火墙是否屏蔽了相应的端口等等),

可以依次尝试以下的方法:

1、重新注册你的 COM 对象,也就是远程数据模块。
2、如果还是有问题,在客户端不用 SocketConnection 来进行调用,而试试通过 CoXXX.Create 来获取中间层接口进行调用(客户端要和中间层运行在同一台机器上),看看能不能成功。
3、通过上述步骤应该能找出问题到底是出现在中间层还是客户端。由于没有源代码,我也不可能知道具体引发错误的原因。楼主可以调试程序来定位错误。
猛禽 2003-09-17
  • 打赏
  • 举报
回复
没辙,重新new 一个中间层的Application,然后把代码COPY过来再BUILD一下试试。

还有一个可能就是你的DELPHI有问题了,重装一哈
hiflower 2003-09-17
  • 打赏
  • 举报
回复
我已经改到最简单了,还是这个现象。

function TBK6YCollectorRemoteDataModule.Login(const UserName,
UserPassword: WideString): Integer;
begin
Result:=1;
end;
猛禽 2003-09-17
  • 打赏
  • 举报
回复
呵呵,没看清:P

正常返回却丢出异常是很奇怪,能不能贴一部分LOGIN的代码来看看是不是有什么问题
hiflower 2003-09-17
  • 打赏
  • 举报
回复
猛禽兄:我的中间层应该就是 应用服务器 了,你指的服务端是什么呢?
猛禽 2003-09-17
  • 打赏
  • 举报
回复
应该调试一下服务端试试。

花兄谦虚,花兄在WebSnap方面的造诣是CSDN的DELPHI版上的XDJM都知道的
hiflower 2003-09-17
  • 打赏
  • 举报
回复
今天,我对中间层进行了调试。
在 safecall 模式下,客户端执行:
SocketConnection1.Open;
if SocketConnection1.AppServer.Login(UserName,UserPassword)<>0 then
ShowMessage('OK')

进入中间层的 Login 方法后,逐条跟踪,并没有产生异常,正常返回。但在客户端却抛出:"无效的被呼叫方"。与上次的 "无效的方法调用" 有所不同。真是怪!

在 stdcall 模式下,则一切正常。程序正确执行。

Login 方法的形式如下:
function Login(UserName,UserPassword:WideString):Integer;

我的中间层和客户端目前运行在同一台电脑上。

请各位指点迷津。

猛禽兄说笑了,我岂敢与诸位相提并论 :)
hiflower 2003-09-16
  • 打赏
  • 举报
回复
请教 leapmars(流铭) :现在奇怪的是用 safecall 的时候,客户端竟然说“无效的方法调用”,与系统设置有没有关系呢?

to idilent(准备去刷碗) : 有没有什么要点呢?
eastliangliang 2003-09-16
  • 打赏
  • 举报
回复
听课,学习
leapmars 2003-09-16
  • 打赏
  • 举报
回复
所以用 safecall 调用约定是比较好的。 和 VC 比较,Delphi 在这方面是很出色的,很多麻烦的工作都由编译器给解决了
leapmars 2003-09-16
  • 打赏
  • 举报
回复
而如果使用 stdcall 调用约定,则 Delphi 就不会做上述的工作。那么就需要自己在客户端使用 OleCheck 来检查调用是否成功。
leapmars 2003-09-16
  • 打赏
  • 举报
回复
对于 dual 接口的方法,Delphi 一般都会把它们的调用约定定义为 safecall,也就是说,如果在被调用方抛出异常的话,调用方能够捕获它(此时的异常类型为EOleException),并且能够获得该异常的详细信息,比如 Message、ErrorCode、Source、HelpFile、HelpContext 等。之所以能够如此,Delphi 在底层做了很多工作,大概过程是:在被调用方抛出异常后,Delphi 通过 CreateErrorInfo、SetErrorInfo 这两个 API 建立并且设置了 COM 的 Error Information Object,而后在调用方通过 GetErrorInfo 获得刚才的 Error Information Object,并且把它转化成 Delphi 中的 EOleException 异常。
加载更多回复(2)

1,593

社区成员

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

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