gpt4 book ai didi

c# - C# 中的联合 - 不正确对齐或与非对象字段重叠

转载 作者:行者123 更新时间:2023-11-30 20:10:42 25 4
gpt4 key购买 nike

我正在通过 PInvoke 编码到需要以下调用的 native C dll。

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

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

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

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 importantly aligned or overlapped by a non-object field. 与以下代码。我相信它可能是字符串之一或整数数组(变量 B7)?我将如何改变它以使其工作 - 我是否必须将整数数组分解为多个变量?

[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 结构并跳过联合即可。在您的外部调用中,只需在方法声明中替换正确的结构。

extern void UnionMethodExpectingA( A a );

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

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

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

针对“长度”参数进行了更新。逻辑仍然适用。只需创建一个“包装器”方法并执行相同的操作即可。

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

关于c# - C# 中的联合 - 不正确对齐或与非对象字段重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4673099/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com