【发布时间】: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对象的大小(不太明显)。
标签: c# c++ interop pinvoke marshalling