Com 错误0x800706F7“;存根收到了错误的数据“;在WindowsXPSP3上

Com 错误0x800706F7“;存根收到了错误的数据“;在WindowsXPSP3上,com,vb6,windows-xp,ada,windows-xp-sp3,Com,Vb6,Windows Xp,Ada,Windows Xp Sp3,在我的VB6应用程序中,我多次调用团队从Ada项目(使用GNATCOM)创建的COM服务器。COM服务器上基本上有两种可用方法。它们在VB中的原型是: Sub PutParam(Param As Parameter_Type, Value) Function GetParam(Param As Parameter_Type) 其中Parameter_Type是一种枚举类型,用于区分我可以放入COM服务器或从COM服务器获取的许多参数,“Value”是一个变量类型变量。PutParam()接收一

在我的VB6应用程序中,我多次调用团队从Ada项目(使用GNATCOM)创建的COM服务器。COM服务器上基本上有两种可用方法。它们在VB中的原型是:

Sub PutParam(Param As Parameter_Type, Value)
Function GetParam(Param As Parameter_Type)
其中Parameter_Type是一种枚举类型,用于区分我可以放入COM服务器或从COM服务器获取的许多参数,“Value”是一个变量类型变量。PutParam()接收一个变量,GetParam()返回一个变量。(我真的不知道为什么在VB6对象浏览器中,COM服务器界面上没有引用变量类型…)

该项目的产品已连续以这种方式使用多年,在使用带SP2的Windows XP的计算机上,该界面没有任何问题。在使用WinXP SP3的计算机上,当尝试将参数设置为“Long”类型时,会出现错误0x800706F7“存根接收到错误数据”

有人知道是什么导致了这一切吗?COM服务器仍在使用SP2的系统中构建。在使用SP3的系统上构建它会有什么不同吗?(就像我们在X64系统中为X64构建时一样)

导致问题的调用之一是以下调用(更改了一些变量名称):

Dim StructData作为StructData\u类型
StructData.FirstLong=1234567
StructData.SecondLong=8901234
StructData.Status=True
ComServer.PutParam(StructDataParamType,StructData)
其中,StructData_类型的定义为:

类型结构数据\u类型
第一,只要
只要
状态为布尔值
端型
(在问题首次发布后添加了以下内容)

IDL中COM服务器接口上原语调用的定义如下:

//接收数据的服务
HRESULT PutParam([in]参数类型参数,[in]变量*值);
//发送请求的数据的服务
HRESULT GetParam([in]参数类型参数[out,retval]变量*值);
我试图通过的结构定义是:

structStructData\u类型
{
int FirstLong;
int秒长;
变异布尔状态;
}结构数据类型;
我发现很奇怪,这里的定义使用“int”作为FirstLong和SeconLong的类型,当我检查VB6对象资源管理器时,它们的类型是“Long”。顺便说一句,当我从COM服务器提取IDL时(使用特定的实用程序),这些参数定义为Long

更新:


我已经用为Windows7编译的COM服务器版本(GNAT的不同版本,GNATCOM的相同版本)测试了相同的代码,它可以工作!我真的不知道这里发生了什么。我将继续尝试确定WinXP SP3上的问题,但很高兴知道它在Win7上工作。如果您有类似的问题,最好尝试迁移到Win7。

如果它突然停止在XP上愉快地工作,我要寻找的第一个罪魁祸首是类型不匹配。这类系统上的“long”现在可能是64位,而您的Ada COM代码(和/或您的C int)可能是32位。对于传统的编译系统,编译器会为您检查这一点,但是COM的额外间接性使得这一点很困难


你在那里写的关于“当我们为64位系统编译时”的部分让我特别警惕。您知道,64位编译可能会改变许多C类型的大小。

这表明您需要在结构中填充,因为编组代码可能需要比实际发送的数据更多的数据(当然这是一个错误)。您的结构包含9个字节(假设每个整数/长4个字节,布尔值1个字节)。尝试添加填充,使您的结构包含4字节的倍数(如果没有,则为8的倍数,因为文章不清楚预期大小)

我将重点解释错误的含义,因为问题中的提示太少,无法提供简单的答案

当您跨执行边界进行调用时,COM中会使用“存根”。问题中没有明确说明,但您的Ada程序可能是一个EXE,并实现了一个进程外COM服务器。在Windows中跨越进程之间的边界是困难的,因为它们具有很强的隔离性。这是在Windows中通过RPC(远程过程调用)完成的,远程过程调用是一种跨此类边界进行调用的协议,典型的情况是网络

要进行RPC调用,必须将函数的参数序列化为网络数据包。COM不知道如何做到这一点,因为它对函数的实际参数了解不够,它需要代理的帮助。一段确实知道参数类型的代码。在接收端是一段非常类似的代码,它的作用与代理完全相反。它反序列化参数并进行内部调用。这是存根

一种可能失败的方法是,存根接收到网络数据包,并且它包含的数据多于或少于函数参数值所需的数据。显然,它不知道该如何处理该数据包,没有合理的方法将其转换为StructData_类型的值,并且它将失败并出现“存根接收到的坏数据”错误

因此,对这个错误的第一个解释是一个DLL地狱问题。代理和存根之间不匹配。如果这个应用程序已经稳定了很长一段时间,那么这不是一个令人高兴的解释

代码片段的另一个方面可能会导致此问题。结构在软件中非常麻烦,它们的成员与其自然存储边界对齐,对齐规则由各自的编译器解释。你所引用的结构肯定是这样。它需要10个字节来存储字段,4+4+2,它们自然对齐。但是这个结构实际上有12个字节长。在末尾填充两个字节,以确保整数仍然对齐