如何在 C# 中 PInvoke 另一个结构内的结构数组
Posted
技术标签:
【中文标题】如何在 C# 中 PInvoke 另一个结构内的结构数组【英文标题】:How to PInvoke in C# an array of structs inside another struct 【发布时间】:2017-01-10 11:12:45 【问题描述】:在 C#.NET 中,我尝试使用此签名从 C++ 程序集(无法访问源代码)中 PInvoke 方法
result_code get_values(values_report_type *values_report)
其中values_report
是指向values_report_type
结构的指针,其中包含我正在查询的值,这些值由该方法返回。结构如下所示:
typedef struct
int countOfValues;
values_type* values;
const char* name;
values_report_type;
其中values
是结构values_type
的数组。
这就是我认为的问题所在:我正在处理的 C++ 程序集除了定义之外没有提供关于 values_type
结构内容的任何信息
typedef struct values_type_struct *values_type
根据文档,这种隐私是故意的。
所以,我的 C# PInvoke 现在看起来像这样:
[DllImport("MyLibrary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
internal static extern result_code get_values(out values_report_type values_report);
internal struct values_report_type
int countOfValues;
IntPtr values;
string name;
这很好,并给了我一个指向 values
结构的指针,但我需要的是访问 values_type
结构的数组并获取指向数组中每个项目的指针(指向每个项目的指针是我所需要的,因为我没有结构内容的定义)。但我想不出一种方法来实现这一点,特别是因为库限制了我对那个结构的描述(甚至没有给出长度)。在 C++ 中,countOfValues
定义的每个项目就像 values_report.values[0]
之类的东西,但我不知道在将其编组到 .NET 时如何让它工作。
有没有办法通过编组在 C# 中解决这个问题?
【问题讨论】:
values
不是struct
的数组。它是一个指向struct values_type_struct
的指针 数组。你打算如何处理values
中的元素?阅读values[i]
很容易(IntPtr Value = Marshal.ReadIntPtr(values_report.values, i*IntPtr.Size)
),接下来发生的事情尚不清楚。
我在 unix 操作系统上工作了很长时间,并多次阅读了整个 UNIX 手册。您必须能够确定每条记录的结束位置的任何结构/数组。通过固定大小的对象、结构中的长度属性或终止字符(如 '\0' \0'。唯一的问题是当 countOfValues 为零时,它看起来像一个 '\0'。因此,在数组的开头,您可能需要添加要发送的数组数量的整数。
@DavidHeffernan SDK 中有更多方法使用指向values_type_struct
元素的指针来执行计算。所以基本上,我无法查看结构的内容,但我可以将指向它的指针发送到另一种计算和转换方法。
听起来不错。如果是这样,那么它就是所谓的不透明指针。在那种情况下,我认为您现在拥有所需的东西。
我能想到的最佳解决方案是尝试生成一个values_type
对象数组,方法是使用Marshal.Copy
将其转换为字节数组,然后将其输入BinarySerializer
。唯一的问题是,为了进行编组,您需要知道要获取的内存量的大小,因此您还需要知道数组的大小(可能由 countOfValues
给出)作为values_type
对象的大小(不太明显)。
【参考方案1】:
values
不是结构数组。它是一个指向结构的 指针 数组。
基于 cmets,并查看代码,您似乎没有 struct 本身的定义。这就是所谓的不透明指针。您不需要知道结构体的大小,只需处理指向结构体的指针,然后将其传回库即可。
像这样从数组中读取不透明的指针值:
IntPtr Value = Marshal.ReadIntPtr(values_report.values, i*IntPtr.Size);
这将获得第 ith 值。
【讨论】:
我可能遗漏了一些东西,但我没有看到values
是结构指针数组的位置。我只是看到它的类型为values_type*
。现在我的 C/C++ 有点初级,但我认为这是指向 single values_type
的指针,它也可以用来表示 values_type
s 的数组。 values_type**
不会表示指针数组吗?
typedef struct values_type_struct *values_type
。所以values_type
是指向结构体的指针。
啊,我明白了。我不习惯寻找 typedef。 :P以上是关于如何在 C# 中 PInvoke 另一个结构内的结构数组的主要内容,如果未能解决你的问题,请参考以下文章