5

对于这些字段的命名,我深表歉意,但我必须根据 NDA 屏蔽字段名称等内容。

所以基本上我在 C# 中,我使用 Interop 与外部库进行通信,这需要通过引用传递特定结构,其中一个使用联合。这是一个似乎让我头疼的结构,因为我在网上找到了一些关于如何将两种数据类型而不是两个结构联合在一起的参考资料。这是两个结构的基础知识

struct datatype1
{ 
    char field1; 
    char field2; 
    char field3;
    char field4;
    char field5; 
    char field6; 
    char field7; 
};

struct datatype2
{
    public uint field8;
    public uint field9;
}

struct datatype3
{
    unsigned int field10;
    union
    {
        datatype1 field11;
        datatype2 field12;
    } field13;
    uint field14;
    unsigned char field15;
    uint field16;
}

在 c# 中生成的结构会是什么样子?我有一些想法,其中一些似乎可行,但一段时间后会导致蓝屏并显示 reference_by_pointer 消息,我在想也许我的结构定义有些问题是错误的,并且不知何故数据不合适在结构中正确。这是我目前拥有的:

    [StructLayout( LayoutKind.Sequential )]
    public struct datatype1
    {
        public byte field1;
        public byte field2;
        public byte field3;
        public byte field4;
        public byte field5;
        public byte field6;
        public byte field7;
    }

    [StructLayout( LayoutKind.Sequential )]
    public struct datatype2
    {
        public uint field8; // Digital i/p event
        public uint field9;
    }

    public struct datatype3
    {
        public uint field10;

        [StructLayout( LayoutKind.Explicit )]
        public struct AnonymousStruct
        {
            [FieldOffset( 0 )]
            public datatype1 field11;

            [FieldOffset( 0 )]
            public datatype2 field12;
        }

        public AnonymousStruct field13;

        public uint field14;

        public byte[] field15;

        public uint field16;
    }

我做这一切都错了吗?

编辑:为了响应更多信息的请求,这里是一个示例用法,但并不是说我无法提供字段的数量,因为它隐藏在 API 中。

此外,这可能是 API 的问题,但这比我把 Interop 搞砸的可能性更大。

    ...inside thread....
    datatype3 dt = new datatype3();
    while( true )
    {
        api.get_next_value( ref dt );
        PrintData( dt );
        Thread.Sleep( 55 );
    }


    /// <summary>
    /// Prints the data from the event.  Used for debugging purposes.
    /// </summary>
    /// <param name="evp"></param>
    private void PrintData( datatype3 evp )
    {
        if( evp.field10 == 2 )
        {
            Console.WriteLine( "datatype2" );
            Console.WriteLine( "\tfield8val: " + evp.field13.field12.field8);
            Console.WriteLine( "\tfield9val: " + evp.field13.field12.field9 );
        }
        else if( evp.de_type == 1 )
        {
            Console.WriteLine( "datatype1" );
            Console.WriteLine( "\tfield1val:  " + evp.field13.field12.field1 );
            Console.WriteLine( "\tfield2val:  " + evp.field13.field12.field2 );
            Console.WriteLine( "\tfield3val:  " + evp.field13.field12.field3 );
            Console.WriteLine( "\tfield4val:  " + evp.field13.field12.field4 );
            Console.WriteLine( "\tfield5val:  " + evp.field13.field12.field5 );
            Console.WriteLine( "\tfield6val:  " + evp.field13.field12.field6 );
            Console.WriteLine( "\tfield7val:  " + evp.field13.field12.field7 );
        }
        else
        {
            return;
        }
    }

对于无法提供绝对的电话或真实的上下文,我深表歉意,但我必须尊重 NDA,即使这意味着降低答案的质量。

编辑2:这两种不同大小的数据类型联合在一起是否有可能对这种情况产生任何影响?我知道 datatype1 的大小为 7 个字节,而 datatype2 的大小为 8 个字节。这会导致某种内存问题吗?

4

1 回答 1

4

您的 C# union 没有问题。然而,field15是错误的。它char在 C 代码和byte[]C# 代码中。您需要像byte在 C# 代码中一样声明它。

对于它的价值,您可以放心省略LayoutKind.Sequential,因为这是结构的默认设置。

于 2013-01-07T21:04:02.813 回答