.net - 解决 x64 com 互操作编码(marshal)处理问题

标签 .net c++ 64-bit com-interop

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

以下是在 C++ 端定义 idl 的一般方式:(忽略愚蠢的 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 位代码中会成为问题?我需要实现一些编码魔法吗?此外,我似乎没有解决编码问题的工具。关于解决编码(marshal)拆收器在幕后所做的事情的好方法有什么建议吗?

最佳答案

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

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

关于.net - 解决 x64 com 互操作编码(marshal)处理问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4082522/

相关文章:

c# - Protected Internal 和 Internal Protected 之间有区别吗?

c++ - 二元运算符和重载、加法等

c - 在简单的 GTK+ 应用程序中启用优化时出现段错误?

c# - 无法手动或自动将 ILNumerics 控件添加到 VS2012 工具箱

.net - 此绑定(bind)的转换器参数应该是什么

javascript - 折叠 Bootstrap Accordion 组

c++ - 用 fstream 在最后一行写

javascript - 将两个32bit寄存器中的64bit除以32bit

c# - 将电子邮件编码为 UTF8

c++ - 容器类成员交互