2010-11-02 133 views
1

我有一个C++ COM服务器,我最近重新编译为64位。这个COM服务器有一个包含struct参数的方法,该参数包含一些int和BSTR以及另一个结构。现在,我试图从64位.Net C#应用程序调用此COM服务器。只要我不尝试填充任何字符串参数,我就可以成功加载我的COM服务器并调用此方法。如果我尝试在int成员中传递有效值,它们最终会在COM对象实现结束时损坏。看起来好像结构被编组的方式是错误的。这段代码在32位应用程序中工作得很好。解决x64 com互操作问题

以下为IDL是在C++侧限定的一般方法:(忽略高飞的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

顺便说一下,我使用添加引用工具添加了对.NET项目的引用。 – 2010-11-02 22:11:29

回答

2

结构是COM的致命弱点。结构成员的实际布局是高度依赖于编译器的。他们在COM自动化方面不支持一段时间,直到他们提出IRecordInfo黑客攻击。没有在这里使用。

在非托管代码中,#pragma pack指令非常重要。对于类型库,midl.exe的/ pack参数非常重要。如果它不是8或者你不使用64位版本的midl,那么你一定会遇到这样的问题。 BSTR成员是那些抛弃它的人,他们是32位或64位指针,具体取决于位数。 32位版本midl的倍数是4,而64位版本的倍数是8。只要结构不包含任何双打,你可以通过传递/包4来拯救它。但首先尝试64位版本的midl.exe。或者摆脱结构并用接口指针替换它们,那才是真正的解决方案。

+0

谢谢。我将类型库'is'导入到另一个C++应用程序时生成的.tlh文件拉出来,发现在每个包含BSTR的结构之前确实存在#pragma pack指令。我认为这将帮助我朝着正确的方向前进。 – 2010-11-03 02:54:40