[英]How to marshal arbitrary structures and unions between C# and C?
我有一个编译为 DLL 的 C 程序,我将其加载到 C#(使用 kernel32.dll LoadLibrary 和 FreeLibrary)。 使用 GetProcAddress 我可以获得指向 memory 中某些数据的指针,我想将此数据转换为 C# 中的等效结构。
我的第一个想法是在 C# 中创建直接映射到 C 结构的结构(使用StructLayout
和MarshalAs
属性),然后只使用Marshal
class(在System.Runtime.InteropServices
中)。 这适用于“更简单”的结构,但不适用于多维 arrays 和 arrays 的联合。
C 中的数据结构如下(举例):
struct MyStruct
{
union MyUnion my_data[16][16];
}
union MyUnion
{
uint32_t ints[2];
uint8_t bytes[8];
}
即,它包含任意嵌套的结构和联合,以及其中的多维 arrays。
C# 中是否有内置方式来处理这些类型的数据结构的编组?
编辑:
我的要求是:
bytes
字段也应该更改ints
字段(afaik,使用显式结构布局,您只能在 C# 中创建内置值类型的联合)。 (这比编组问题更像是 C# 问题)正如 Selvin 在评论中指出的那样,可以将多维 arrays 展平为一个维度,然后通过 [x + y*16] 访问。 但是我更喜欢保留原始尺寸,并且访问方法与C中的相同。
我在下面的回答符合我的要求,但由于 C# 和 C++ 之间的编组非常普遍,所以感觉应该有一种更简单的方法来实现该结果。
我当前的解决方案是围绕原始数据byte[]
创建一个包装器 class,并使用模仿底层数据结构的访问器。
例如,对于 C 中的一个简单结构:
struct MySimpleStruct
{
uint32_t my_ints[16];
}
我创建一个包装器:
public class MySimpleStruct
{
private byte[] _underlying;
public UintAccessor[] MyInts { get; }
public MySimpleStruct(byte[] data)
{
_underlying = data;
MyInts = new UintAccessor[16];
// for-loop to initialize each accessor with the right index
}
}
public class UintAccessor
{
public uint Value
{
get => BitConverter.ToUint32(_underlying, _idx);
set => BitConverter.GetBytes(value).CopyTo(_underlying, _idx);
}
public UintAccessor(byte[] data, int index) { /* ... */ }
}
包装纸可以像这样使用
var myStruct = new MySimpleStruct(theData);
myStruct.MyInts[5].Value = 123;
这些包装器类可能会变得相当复杂,但是我们会自动生成 C 结构,同时我们将生成这些 C# 包装器,因此复杂性只是生成代码时的一个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.