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

3
什么是最好的方式来适应以下情况:
实时性能关键应用程序,与本地C dll接口通信以与专有后端通信。
本机API具有数百个结构、嵌套结构和方法,通过这些结构传递数据。
想要使用c#进行逻辑处理,因此选择了不安全的c#而不是cli和马歇尔。我知道如何实现这一点,并已经通过后者实现了这一点,请不要回复“使用cli”。每秒传输数百次结构引入了足够大的延迟,需要调查不安全的c#。
大多数c结构包含数十个字段,因此正在寻找一种在每个字段上进行最小输入的方法。目前,我已经将其简化为运行VS宏,将每个行元素转换为c#等效设置数组大小时需要注意。这很有效,直到我遇到一个嵌套结构数组。例如,我有这两个结构:
[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]
}

如何最好地容纳固定的用户 users[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中已经有足够多这样的代码了,我希望避免这种方法,但如果有人能展示一种优雅的方式,那也可以。第三种方法让我感到困惑,我无法提供一个例子(我记得我在某个地方看到过,但现在找不到了),就是为User指定大小或以某种方式使其严格大小,以便您可以在其上使用“fixed”关键字。有人能推荐一个合理的方法吗?他们已经使用并且在负载下扩展得很好?
1个回答

1

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

[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.获取并修复指向结构体的字节数组的不安全指针 4.将内存从一个复制到另一个
之所以不将托管数组存储回结构体本身,是因为这会修改其布局,并且在从非托管获取时不会正确翻译,而prop在获取时不会出现问题。或者,可以将其包装在另一个执行存储操作的托管对象中。

我真的很希望能得到一些反馈,因为我不知道在压力下它会表现如何。 - Dmitry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接