huysentruitw
huysentruitw

Reputation: 28141

Get fixed array values from unsafe struct

I'm using an external C library that comes with a C# wrapper file containing a struct like (among many other things):

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

I can get the values by adding an additional method to that struct:

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

But this is not what I want because I don't want to touch the wrapper file (to avoid having to keep the external file in our SCM repository). Whatever I try to do to get the values from outside that struct results in the following error:

Fixed size buffers can only be accessed through locals or fields

What I've tried:

Is there any way to get around this?

Upvotes: 2

Views: 1249

Answers (2)

Blindy
Blindy

Reputation: 67439

Rather than patch your code up, have you considered shoving this over to the marshaller? That's its entire purpose: to assist with native interop while letting you write pure managed code.

You'd have to declare your struct like this:

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

When this structure is filled by the marshaller (through either a direct function call through a pointer, or from mapping the struct on top of a byte buffer) it will allocate the proper array and copy its contents over. This makes your entire function obsolete, but if you really wanted to you could simply use Array.Copy (or the Linq equivalent).

Notice there's no more unsafe modifier. You can run this in a partially trusted environment with no issues!

Upvotes: 0

huysentruitw
huysentruitw

Reputation: 28141

Suddenly the word 'extension method' crossed my mind. And yes, I have it working:

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

Upvotes: 2

Related Questions