我有一个C ++ COM服务器,我最近重新编译为64位。此COM服务器有一个方法,其中包含一个struct参数,该参数包含一些int和BSTR以及另一个结构。现在,我试图从64位.Net C#应用程序调用此COM服务器。我可以成功加载我的COM服务器并调用此方法,只要我不尝试填充任何字符串参数。如果我尝试在int成员中传递有效值,它们最终会在COM对象实现结束时被破坏。看起来结构被编组的方式似乎是错误的。这段代码在32位应用程序中运行良好。
以下是在C ++端定义idl的一般方法:(忽略goofy typedef,它是一些遗留代码)
[helpstring("method Method1")] HRESULT Method1([in] STRUCT1* pStruct, [in, out] DWORD* inparm1, [out]USHORT* outparm2);
typedef struct _Struct2
{
USHORT p1;
BSTR s1;
BSTR s2;
BSTR s3;
BSTR s4;
DWORD p2;
DWORD p3;
} STRUCT2;
typedef struct _Struct1
{
DWORD p1;
DWORD p2;
BSTR s1;
BOOL p3;
STRUCT2 struct2;
}STRUCT1;
尝试填充STRUCT2中的成员会导致未定义的行为和崩溃。任何人都可以看到为什么这将是64位经文32位代码的问题?我需要做一些编组魔术吗?此外,我似乎没有解决编组问题的工具。有关解决编组人员在幕后做什么的好方法的任何建议吗?
答案 0 :(得分:2)
结构是COM的致命弱点。结构成员的实际布局高度依赖于编译器。在他们想出IRecordInfo hack之前,他们不会在COM自动化中支持很长一段时间。没有在这里使用。
在非托管代码中,#pragma pack指令非常重要。对于类型库,midl.exe的/ pack参数是必不可少的。如果它不是8或你不使用64位版本的midl那么你肯定会遇到这种问题。 BSTR成员是将其丢弃的成员,它们是32位或64位指针,具体取决于位数。对于32位版本的midl,对齐4的倍数,对于64位版本,对齐为8的倍数。只要结构不包含任何双精度数,您就可以通过传递/ pack 4来拯救它。但首先尝试64位版本的midl.exe。或者去除结构并用接口指针替换它们,这才是真正的修复。