C#中的并集-错误对齐或与非对象字段重叠 [英] Unions in C# - incorrectly aligned or overlapped with a non-object field

查看:542
本文介绍了C#中的并集-错误对齐或与非对象字段重叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过PInvoke编组到本机C dll,该dll希望进行以下调用.

I am marshaling via PInvoke to a native C dll which expects the following call.

private static extern int externalMethod(IntPtr Data, [MarshalAs(UnmanagedType.U4)] ref int dataLength);

dataLength参数是通过IntPtr Data参数传递的结构的长度.如果两者不匹配,则会引发异常.外部方法使用C联合将四种类型结合在一起.

The dataLength parameter is the length of the struct being passed via the IntPtr Data parameter. It throws an exception if the two do not match. The external method uses a C Union joining together four types.

我已经通过使用FieldOffsetAttribute在C#中重新创建了联合.然后,我正在计算C#联合的长度,并使用以下命令调用该方法:

I've managed to recreate unions in C# by using the FieldOffsetAttribute. I am then calculating the length of the C# union and calling the method with the following:

int len = Marshal.SizeOf(data);
IntPtr ptr = Marshal.AllocCoTaskMem(len);
externalMethod(ptr, len);

但是,出现以下代码错误System.TypeLoadException : ... Could not load type because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field..我相信它可能是字符串之一还是整数数组(变量B7)?我将如何进行更改以使其起作用-我必须将整数数组分解为多个变量吗?

However, I get the error System.TypeLoadException : ... Could not load type because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field. with the following code. I believe it is perhaps either one of the strings or the integer array (variable B7)? How would I go about changing this to make it work - do I have to break the integer array into multiple variables?

[StructLayoutAttribute(LayoutKind.Explicit)]
public struct Union{
    [FieldOffset(0)]
    public A a;

    [FieldOffset(0)]
    public B b;

    [FieldOffset(0)]
    public C c;

    [FieldOffset(0)]
    public D d;
}

[StructLayout(LayoutKind.Sequential)]
public struct A
{
    public int A1;
    public int A2;
    public int A3;
    [MarshalAs(UnmanagedType.LPTStr, SizeConst = 17)]
    public string A4;
    [MarshalAs(UnmanagedType.LPTStr, SizeConst = 4)]
    public string A5;
}

[StructLayout(LayoutKind.Sequential)]
public struct B
{
    public int B1;
    [MarshalAs(UnmanagedType.LPTStr, SizeConst = 2)]
    public string B2;
    [MarshalAs(UnmanagedType.LPTStr, SizeConst = 4)]
    public string B3;
    [MarshalAs(UnmanagedType.LPTStr, SizeConst = 6)]
    public string B4;
    public int B5;
    public int B6;
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U4, SizeConst = 255)]
    public int[] B7;
}

[StructLayout(LayoutKind.Sequential)]
public struct C
{
    public int C1;
    public int C2;
    public int C3;
    public int C4;
    [MarshalAs(UnmanagedType.LPTStr, SizeConst = 32)]
    public string C5;
    public float C6;
    public float C7;
    public float C8;
    public float C9;
    public float C10;
    public float C11;
    public float C12;
    public float C13;
    public float C14;
}

[StructLayout(LayoutKind.Sequential)]
public struct D
{
    public int D1;
    [MarshalAs(UnmanagedType.LPTStr, SizeConst = 36)]
    public string D2;
}

推荐答案

只需直接使用A/B/C/D结构,并跳过联合.在您的外部调用中,只需在方法声明中替换正确的结构即可.

Just use the A/B/C/D structs directly and skip the union. In your extern calls, simply substitute the correct struct in the method declaration.

extern void UnionMethodExpectingA( A a );

如果非托管方法实际上接受一个联合并根据传递的类型而表现不同,那么您可以声明不同的extern方法,这些方法最终都调用同一非托管入口点.

If the unmanaged methods actually accept a union and behave differently based on the type passed, then you can declare different extern methods that all end up calling the same unmanaged entry point.

[DllImport( "unmanaged.dll", EntryPoint="ScaryMethod" )]
extern void ScaryMethodExpectingA( A a );

[DllImport( "unmanaged.dll", EntryPoint="ScaryMethod" )]
extern void ScaryMethodExpectingB( B b );

已更新长度"参数. 逻辑仍然适用.只需创建一个包装器"方法并执行相同的操作即可.

Updated for "length" parameter. The logic still applies. Just create a "wrapper" method and do the same thing.

void CallScaryMethodExpectingA( A a )
{
  ScaryMethodExpectingA( a, Marshal.SizeOf( a ) );
} 

这篇关于C#中的并集-错误对齐或与非对象字段重叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆