Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# -- Create Managed Array from Pointer

I'm trying to create a Managed Array of doubles from an array of bytes. I have the problem working currently, but I wanted to optimize. Here's some code that I would like to work:

private unsafe static double[] _Get_Doubles(byte[] _raw_data)
{
    double[] ret;
    fixed (byte* _pd = _raw_data)
    {
        double* _pret = (double*)_pd;
        ret = (double[])*_pret; //FAILURE
    }
}

Please let me know how to cope with these problems.

-Aaron

like image 480
lmat - Reinstate Monica Avatar asked Dec 16 '09 17:12

lmat - Reinstate Monica


2 Answers

One of the key things to notice about the code you have posted is that there is no way to know how many items are pointed to by the return value, and a managed array needs to know how big it is. You can return a double* or create a new double[XXX] and copy the values or even (if the count is constant) create a struct with a public fixed double _data[2]; member and cast the raw data to that type.

like image 196
Dolphin Avatar answered Sep 27 '22 17:09

Dolphin


Just now, I thought that stackalloc would be the right way, but it fails. Most importantly, I now know that it was doomed to fail. There is no way to do what I want to do.

This can be seen by restating the question:

How can I create a managed array around an 'unsafe' array?

Since a managed array has header information (because it's a class around a chuck of memory), it requires more space in memory than the array itself. So, the answer is:

Allocate space before (and/or after? depending on the way managed arrays are stored in memory) the array itself and put the managed information (length, (et cetera)) around the 'unsafe' array.

This is not easily possible because to guarantee that there is data enough around the array is shaky at best. In my particular example there may be enough space for it because a managed byte[] is passed in meaning that there is data around the array, but to assert that the same data is appropriate for managed double[] is dubious at best, but most likely erroneous, and to change the data to make it appropriate for managed double[] is nefarious.

[EDIT]

It looks like Marshal.Copy is the way to go here. Create a new array and let Marshal copy them (hoping that he will be quicker than me, or that perhaps at some later date, he will be quicker):

var ret = new double[_raw_data.Length / sizeof(double)];
System.Runtime.InteropServices.Marshal.Copy(new System.IntPtr(_pret), ret, 0, ret.Length);
like image 28
lmat - Reinstate Monica Avatar answered Sep 27 '22 18:09

lmat - Reinstate Monica