对 x64 com 互操作封送问题进行故障排除 [英] Troubleshooting an x64 com interop marshaling issue

查看:40
本文介绍了对 x64 com 互操作封送问题进行故障排除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 C++ COM 服务器,我最近将它重新编译为 64 位.此 COM 服务器有一个方法,该方法包含一个结构参数,该参数包含一些整数和一个 BSTR 以及另一个结构.现在,我试图从 64 位 .Net C# 应用程序调用这个 COM 服务器.只要我不尝试填充任何字符串参数,我就可以成功加载我的 COM 服务器并调用此方法.如果我尝试在 int 成员中传递有效值,则它们最终会在 COM 对象实现处结束时损坏.似乎结构的编组方式是错误的.此代码在 32 位应用程序中运行良好.

I have a C++ COM Server which I have recently recompiled to 64 bit. This COM server has a method that contains a struct parameter which contains some ints and a BSTR and another structure. Now, I am trying to call this COM server from a 64 bit .Net C# application. I can successfully load my COM server and call this method as long as I don't try to populate any of the string parameters. If I try to pass valid values in the int members, they end up corrupted by the time the end up at the COM object implementation. It appears as though the way the structure is marshaled is just wrong. This code worked just fine in 32 bit applications.

以下是在C++端定义idl的一般方式:(忽略愚蠢的typedef,这是一些遗留代码)

The following is the general way the idl is defined on the C++ side: (ignore the goofy typedefs, it's some legacy code)

[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 位代码中会出现问题?我需要实现一些编组魔法吗?此外,我似乎没有解决封送问题的工具.关于解决封送拆收器在幕后做什么的好方法有什么建议吗?

Attempting to populate the members in STRUCT2 causes undefined behavior and crashes. Can anyone see why this would be a problem in 64 bit verses 32 bit code? Is there some marshaling magic I need to make happen? Additionally, I don't seem to have the tools to troubleshoot marshaling issues. Any suggestions on a good way to troubleshoot what the marshaler is doing under the covers?

推荐答案

结构是 COM 的致命弱点.结构成员的实际布局高度依赖于编译器.在他们提出 IRecordInfo hack 之前,它们在很长一段时间内都不受 COM 自动化支持.在这里不习惯.

A struct is COM's Achilles heel. The actual layout of the members of the struct is highly compiler dependent. They were not support in COM automation for quite a while until they came up with the IRecordInfo hack. Not getting used here.

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

In unmanaged code, the #pragma pack directive is very important. For type libraries, the /pack argument to midl.exe is essential. If it isn't 8 or you don't use the 64-bit version of midl then you'll definitely have this kind of problem. The BSTR members are the ones that throw it off, they are either 32-bit or 64-bit pointers, depending on the bitness. And align on a multiple of 4 for the 32-bit version of midl, a multiple of 8 for the 64-bit version. You can possible rescue it by passing /pack 4, as long as the struct doesn't contain any doubles. But try the 64-bit version of midl.exe first. Or get rid of structs and replace them with interface pointers, that's the real fix.

这篇关于对 x64 com 互操作封送问题进行故障排除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆