How to fix System.TypeLoadException when declaring structs with union?

浪尽此生 提交于 2021-02-11 14:17:16

问题


Receiving System.TypeLoadException in runtime. I use code from third-party source to define structs and p-invoke external methods.

I found the full code online in this link.

In the code there are some structs with union, using FieldOffsetAttribute(0) on multiple fields. when I try to use some of the structs I get an exception:

Could not load type 'NET_DVR_SLAVE_CHANNEL_UNION' from assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field.

Ive created a sample project that reproduce this behavior using two structs from the original file.

this code used to work, after I split the app into two different assemblies and dynamically loaded the assembly containing the third party code and used reflection to get types from the loaded assembly. this forced loading the types and caused the error to be thrown, until now those types were not in use so we didn't know about the problem.

As a temporary solution, I removed those types from the code.

A co-worker suggested that some of the fields are 'blittable' referring to byte arrays. But those fields are decorated with MarshalAsAttribute, so I guess that should make it fine.

{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;
        }
    }
}

Can this issue be solved by adding a MarshalAsAttribute to NET_DVR_CHANNEL?

code examples and/or referring me to an explanation of how to solve this would be much appreciated. also, an explanation of what is wrong in the code would be gladly received.

来源:https://stackoverflow.com/questions/54240120/how-to-fix-system-typeloadexception-when-declaring-structs-with-union

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!