从不安全的struct获取固定数组值

时间:2015-02-16 16:41:35

标签: c#

我使用的外部C库附带了一个包含结构的C#包装器文件(在许多其他方面):

[StructLayout(LayoutKind.Sequential, Pack = 8)]
unsafe public struct Data
{
    public fixed double Values[3];
};

我可以通过向该结构添加一个额外的方法来获取值:

public double[] CopyFixedDoubleArray()
{
    double[] result = new double[3];
    fixed (double* pDst = result)
    {
        fixed (double* pSrc = Values)
        {
            double* pd = pDst;
            double* ps = pSrc;
            for (int i = 0; i < result.Length; i++)
            {
                *pd = *ps;
                pd++; ps++;
            }
        }
    }
    return result;
}

但这不是我想要的,因为我不想触摸包装文件(以避免将外部文件保留在我们的SCM存储库中)。无论我尝试从结构外部获取值,都会导致以下错误:

  

固定大小的缓冲区只能通过本地或字段访问

我尝试过的事情:

  • double a = data.Values[2];
  • double a; unsafe { a = data.Values[2]; }
  • double a; fixed (double* p = data.Values) { a = p[2]; }
  • fixed (double a = data.Values[2]) { /* use a */ }

有没有办法解决这个问题?

2 个答案:

答案 0 :(得分:1)

突然间,这个词的扩展方法&#39;克服了我的想法。是的,我有它的工作:

public static double[] CopyFixedDoubleArray(this Data data)
{
    unsafe
    {
        return new[] { data.Values[0], data.Values[1], data.Values[2] };
    }
}

答案 1 :(得分:-1)

您是否考虑过将其推送给编组员,而不是修补您的代码?这就是它的全部目的:在让你编写纯托管代码的同时协助本地互操作。

你必须声明你的struct

[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct Data
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public double[] Values;
};

当这个结构由编组器填充时(通过指针直接调用函数,或者从字节缓冲区顶部映射struct),它将分配正确的数组并复制其内容。这会使您的整个功能过时,但如果您真的想要,可以简单地使用Array.Copy(或等效的Linq)。

请注意,不再有unsafe修饰符。您可以在部分受信任的环境中运行它,没有任何问题!