用联合声明结构时如何修复System.TypeLoadException?

时间:2019-01-17 16:19:48

标签: c# struct interop pinvoke unions

在运行时接收System.TypeLoadException。 我使用来自第三方的代码来定义结构并p调用外部方法。

我在this链接中在线找到了完整的代码。

代码中有一些带有并集的结构,在多个字段上使用FieldOffsetAttribute(0)。当我尝试使用某些结构时,出现异常:

  

无法从程序集'ClassLibrary1,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'中加载类型'NET_DVR_SLAVE_CHANNEL_UNION',因为它包含偏移量为0的对象字段,该对象字段错误地对齐或与非对象字段重叠

我创建了一个示例项目,该示例项目使用原始文件中的两个结构来重现此行为。

在我将应用程序分为两个不同的程序集并动态加载包含第三方代码的程序集并使用反射从加载的程序集获取类型之后,该代码就可以正常工作了。这会强制加载类型并导致引发错误,直到现在这些类型都没有使用,所以我们对这个问题一无所知。

作为临时解决方案,我从代码中删除了这些类型。

一位同事建议某些字段是“可字节调的”,指的是字节数组。但是这些字段都用MarshalAsAttribute装饰,因此我认为应该可以解决问题。

{using System.Runtime.InteropServices;
namespace ClassLibrary1
{
    public class Class1
    {
        public const int MAX_DOMAIN_NAME = 64;
        public const int NAME_LEN = 32;
        public const int PASSWD_LEN = 16;

        [StructLayoutAttribute(LayoutKind.Sequential)]
        public struct NET_DVR_CHANNEL
        {
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = MAX_DOMAIN_NAME, ArraySubType = UnmanagedType.I1)]
            public byte[] byAddress;
            public ushort wDVRPort;
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.I1)]
            public byte[] byRes1;
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NAME_LEN, ArraySubType = UnmanagedType.I1)]
            public byte[] sUserName;
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = PASSWD_LEN, ArraySubType = UnmanagedType.I1)]
            public byte[] sPassword;
            public uint dwChannel;
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.I1)]
            public byte[] byRes2;
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct NET_DVR_SLAVE_CHANNEL_UNION
        {
            [FieldOffsetAttribute(0)]
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 152, ArraySubType = UnmanagedType.I1)]
            public byte[] byRes;
            [FieldOffsetAttribute(0)]
            public uint dwLocalChannel;
            [FieldOffsetAttribute(0)]
            public NET_DVR_CHANNEL struRemoteChannel;
        }
    }
}
}


using static ClassLibrary1.Class1;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            NET_DVR_CHANNEL instance_NET_DVR_CHANNEL;
            NET_DVR_SLAVE_CHANNEL_UNION instance_NET_DVR_SLAVE_CHANNEL_UNION;
        }
    }
}

可以通过向NET_DVR_CHANNEL添加MarshalAsAttribute来解决此问题吗?

代码示例和/或让我参考如何解决此问题的解释。另外,很高兴收到关于代码错误的解释。

0 个答案:

没有答案