gpt4 book ai didi

c# - 带有 char 数组的非托管联合

转载 作者:太空宇宙 更新时间:2023-11-03 16:26:37 25 4
gpt4 key购买 nike

我在 C++ 中有以下内容:

struct TestA {
int i;
char text[512];
};

struct TestB {
double n;
char text[512];
};

union TestUnion {
struct TestA a;
struct TestB b;
};

int fnUnmanagedDLL(int which,TestUnion *);

我试过像这样声明一个 C# 包装器:

public class WrapperClass
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct TestA
{
public int i;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 512)]
public string text;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct TestB
{
public double n;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 512)]
public string text;
}
[StructLayout(LayoutKind.Explicit)]
public struct TestUnion
{
[FieldOffset(0)]
public TestA a;

[FieldOffset(0)]
public TestB b;

}

[DllImport("UnmanagedDLL.Dll")]
public static extern int fnUnmanagedDLL(int which,ref TestUnion obj);
}

只要我运行一个引用 WrapperClass.TestUnion 的程序,我就会得到“无法从程序集‘UnmanagedToManaged, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’中加载类型‘TestUnion’,因为它包含一个对象偏移量为 0 的字段未正确对齐或被非对象字段重叠。”。

这只是一个测试程序。我确实在另一个问题中看到了删除 untion 的建议。但是,我不知道DLL会提前填充哪个结构。谁能就我做错了什么提供建议?

最佳答案

默认编码器无法自动处理此问题。它不知道从非托管函数返回时如何编码结构,因为它无法知道它应该使用 TestUnion 的哪一部分。您必须通过更改 p/Invoke 定义以采用 IntPtr、分配缓冲区,然后手动编码(marshal)至正确的类型来手动执行编码(marshal)处理。

在下面的示例中,我假设 fnUnmanagedDLL 的返回值是您确定它填充的结构类型的方式。

public class WrapperClass
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct TestA
{
public int i;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 512)]
public string text;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct TestB
{
public double n;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 512)]
public string text;
}

public struct TestUnion // Removed marshal attributes since they cause exceptions
{
public TestA a;
public TestB b;
}

[DllImport("UnmanagedDLL.Dll")]
private static extern int fnUnmanagedDLL(int which, IntPtr obj);

public static int UnmanagedDLL(int which, ref TestUnion testUnion) {
IntPtr buffer = Marshal.AllocHGlobal(
Math.Max(Marshal.SizeOf(typeof(TestA)),
Marshal.SizeOf(typeof(TestB)));

int returnType = fnUnmanagedDLL(which, buffer);
switch (returnType) {
case 1: // What ever fnUnmanagedDLL returns for TestA
testUnion.a = (TestA)Marshal.PtrToStructure(buffer, typeof(TestA));
break;
case 2: // What ever fnUnmanagedDLL returns for TestB
testUnion.a = (TestB)Marshal.PtrToStructure(buffer, typeof(TestB));
break;
}

Marhsal.FreeHGlobal(buffer); // Need to manually free the allocated buffer

return returnType;
}
}

关于c# - 带有 char 数组的非托管联合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12390379/

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