COM接口 c# marshalling array of arrays

Posted

技术标签:

【中文标题】COM接口 c# marshalling array of arrays【英文标题】:COM interface c# marshalling array of arrays 【发布时间】:2019-03-28 21:58:47 【问题描述】:

我有一个用 C++ 编写的 COM 服务器,它应该与用 C# 编写的客户端接口。 C++ COM 服务器将接口函数导出到一个结构中,该结构包含一个结构数组,其中包含一个数组

struct InnerStruct   int innerArray[ 100 ]; 
struct OuterStruct   int dummy; InnerStruct outerArray[ 2 ]; 

所以结构的大小是固定的。

IDL 描述是

HRESULT SetStruct( [in] const OuterStruct* par, [out, retval] int code );
HRESULT GetStruct( [out] OuterStruct* par, [out, retval] int code );

IDL 编译正常,我可以在 C# 客户端中看到结构。

问题是当我从 C# 客户端调用接口函数时,我只获取/设置 OuterStruct 中第一个 InnerStruct 中的值。 第二个 InnerStruct 只保存垃圾。

C# 调试器显示 OuterStruct 的正确结构,并知道 OuterStruct 中有 2 个 InnerStruct。

在C#中,接口函数的声明来自一个服务器元文件,所以不容易改变描述。

我尝试在 in 和 out 参数上设置 size_is(),但 MIDL 编译器不接受。

能否在参数上设置一些特定的编组,或者如何解决通过 COM 获取完整 OuterStruct 的问题?

【问题讨论】:

1) 您确定 MIDL 编译时没有警告(例如,关于忽略的说明符)?因为看到不是指针的out 参数很奇怪。 2)“我试图设置 size_is()size_is 将有一个目的,如果你将传递多个 OuterStructs,而,如果我理解正确,你只是传递一个(即使那样,size_is 需要额外的参数来指定大小)。我从来没有在 COM 中涉足过这样的结构。今天晚些时候可以尝试这样做。 我尝试写 [in, size_is(1000)]。 我得到的错误码是 midl:错误 MIDL2471:idl 和/或包含/导入的 idl 文件中的某些属性和/或数据类型无法在类型库中表示:size_is/max_is 1) "我试着写[in, size_is(1000)]" 试着写吧,在哪里?在[in] const OuterStruct* par?如果是这样,您应该将OuterStruct par[1000] 传递给它,我怀疑这是您的意图。即便如此,我从未对size_is 使用硬编码值,所以我不知道size_is 是否支持使用硬编码值。 2) 确保您的 idl 编译时没有警告。 3)您可以编辑您的 cmets,因此您不会评论垃圾邮件。 【参考方案1】:

在我尝试写入的 IDL 文件中

typedef [transmit_as(OuterStructAliasType)] OuterStruct* HelpType;

并将其他声明保留为

HRESULT SetStruct( [in] const OuterStruct* par, [out, retval] int code );
HRESULT GetStruct( [out] OuterStruct* par, [out, retval] int code );

我在 C++ 代码中定义的位置

typedef struct OuterStructAliasType

    char    dummy[ sizeof( OuterStruct )];
 OuterStructAliasType;

这似乎有效。 也许还有其他方法可以解决问题。 请告诉我他们更聪明或更好。

【讨论】:

以上是关于COM接口 c# marshalling array of arrays的主要内容,如果未能解决你的问题,请参考以下文章

如何手动将 .NET 对象编组为双 COM 接口?

C# Marshal

C# Marshal

c#中Marshal.Copy()方法的使用

C# Marshal类基本概念和入门示例程序

注册 C# 委托给 C++ 回调,Marshal.GetFunctionPointerForDelegate 有啥作用?