在C#中容纳嵌套的不安全的结构

时间:2013-10-03 20:26:52

标签: c# c++ c struct unsafe

满足以下条件的最佳方法是什么:

与本机C dll连接以与专有后端通信的实时,性能关键型应用程序。

原生api有数百个结构,嵌套结构和方法,通过这些结构来回传递数据。

想要使用c#作为逻辑,所以决定使用不安全的c#来支持cli和marshaling。我知道如何通过后来实现这一点,所以请不要回复“使用cli”。每秒数百次对数百个结构进行编组会引入足够大的延迟,因此需要调查不安全的c#。

大多数c结构包含许多字段,因此寻找一种方法在每个字段上进行最小的输入。此时,在运行VS宏时,必要时将每个行元素转换为c#等效设置数组为固定大小。这个工作很好,直到我点击嵌套的struct数组。例如,我有这两个结构:

[StructLayout(LayoutKind.Sequential,Pack=1)]
unsafe struct User{
    int id;
    fixed char name[12];
}

[StructLayout(LayoutKind.Sequential,Pack=1)]
unsafe structs UserGroup{
    fixed char name[12];
    fixed User users[512]
    int somethingElse;
    fixed char anotherThing[16]
}

适应固定用户用户[512]的最佳方法是什么,以便在运行时不必做太多工作?

我已经看过建议要做的例子

[StructLayout(LayoutKind.Sequential,Pack=1)]
unsafe structs UserGroup{
    fixed char name[12];
    User users_1;
    User users_2;
    ...
    User users_511;
    int somethingElse;
    fixed char anotherThing[16]
}

另一个想法是,以字节为单位计算用户的大小,然后执行此操作

[StructLayout(LayoutKind.Sequential,Pack=1)]
unsafe structs UserGroup{
    fixed char name[12];
    fixed byte Users[28*512];
    int somethingElse;
    fixed char anotherThing[16]
}

但这意味着每次我需要使用它时,我都必须对这个结构进行特殊处理,或者用其他代码包装它。在api中有足够的那些我想避免这种方法,但如果有人可以展示一种优雅的方式我也可以工作

第三种方法让我筋疲力尽,我无法生产和示例(我想我看到了某个地方但又找不到它),是指定用户的大小或以某种方式使其严格按照大小调整,以便您可以使用“固定“关键字就可以了。

任何人都可以推荐他们使用的合理方法,并在负载下很好地扩展吗?

1 个答案:

答案 0 :(得分:0)

我在不安全的结构中找到嵌套结构的最好方法是将它们定义为固定字节数组,然后为字段提供运行时转换属性。例如:

[StructLayout(LayoutKind.Sequential,Pack=1)]
unsafe struct UserGroup{
    fixed char name[12];
    fixed User users[512]
    int somethingElse;
    fixed char anotherThing[16]
}

变成:

[StructLayout(LayoutKind.Sequential,Pack=1)]
unsafe struct UserGroup{
    fixed char name[12];
    fixed byte users[512 * Constants.SizeOfUser]
    int somethingElse;
    fixed char anotherThing[16];
    public User[] Users
    {
        get
        {
            var retArr = new User[512];
            fixed(User* retArrRef = retArr){
                fixed(byte* usersFixed = users){
                    {
                        Memory.Copy(usersFixed, retArrRef,  512 * Constants.SizeOfUser);
                    }
                }
            }
            return retArr;
        }
    }
}

请注意,此代码使用此处提供的Memory.Copy函数:http://msdn.microsoft.com/en-us/library/aa664786(v=vs.71).aspx

geter的一般解释如下:

  1. 为返回值分配托管数组
  2. 获取并修复指向它的不安全指针
  3. 获取并修复指向struct
  4. 的字节数组的不安全指针
  5. 将内存从一个复制到另一个
  6. 托管数组之所以没有被存储回自己的结构是因为它会修改它的布局而不再正确转换,而从非托管中获取它时道具是没有问题的。或者,这可以包装在另一个进行存储的托管对象中。