Fixing an array of array in C# (unsafe code)
Asked Answered
F

3

7

I'm trying to come up with a solution as to how I can pass an array of arrays from C# into a native function. I already have a delegate to the function (Marshal.GetDelegateForFunctionPointer), but now I'm trying to pass a multidimensional array (or rather; an array of arrays) into it.

This code example works when the input has 2 sub-arrays, but I need to be able to handle any number of sub-arrays. What's the easiest way you can think of to do that? I'd prefer not to copy the data between arrays as this will be happening in a real-time loop (I'm communicating with an audio effect)

public void process(float[][] input)
{
    unsafe
    {
        // If I know how many sub-arrays I have I can just fix them like this... but I need to handle n-many arrays
        fixed (float* inp0 = input[0], inp1 = input[1] )
        {
            // Create the pointer array and put the pointers to input[0] and input[1] into it
            float*[] inputArray = new float*[2];
            inputArray[0] = inp0;
            inputArray[1] = inp1;
            fixed(float** inputPtr = inputArray)
            {
                // C function signature is someFuction(float** input, int numberOfChannels, int length)
                functionDelegate(inputPtr, 2, input[0].length);
            }
        }
    }
}
Farman answered 14/11, 2011 at 19:59 Comment(0)
T
12

You can pin an object in place without using fixed by instead obtaining a pinned GCHandle to the object in question. Of course, it should go without saying that by doing so you take responsibility for ensuring that the pointer does not survive past the point where the object is unpinned. We call it "unsafe" code for a reason; you get to be responsible for safe memory management, not the runtime.

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle.aspx

Toadflax answered 14/11, 2011 at 20:10 Comment(1)
I had read about the GCHandle class. After reading your reply I tried implementing it for my call and it seems to be working pretty well. Thank you for a quick answer.Farman
B
0

It makes no sense trying to lock the array of references to the managed arrays.

The references values in there probably don't point to the adress of the first element, and even if they did, that would be an implementation detail. It could change from release to release.

Copying an array of pointers to a lot of data should not be that slow, especcially not when compared with the multimedia processing you are calling into.

If it is significant, allocate your data outside of the managed heap, then there is no pinning or copying. But more bookkeeping.

Byproduct answered 14/11, 2011 at 20:10 Comment(0)
S
0

The easiest way I know is to use one dimension array. It reduce complexity, memory fragmentation and also will have better performance. I actually do so in my project. You can use manual indexing like array[i][j] = oneDimArray[i *n + j] and pass n as param to a function. And you will do only one fixing just like you done in your example:

public void process(float[] oneDimInput, int numberOfColumns)
{
    unsafe
    {
        fixed (float* inputPtr = &oneDimInput[0])
        {
                // C function signature is someFuction(
                // float* input, 
                // int number of columns in oneDimInput
                // int numberOfChannels, 
                // int length)
                functionDelegate(inputPtr, numberOfColumns, 2, oneDimInput[0].length);
        }
    }
}

Also I need to note, that two dimension arrays rarely used in high performance computation libraries as Intel MKL, Intel IPP and many others. Even BLAS and Lapack interfaces contain only one dimension arrays and emulate two dimension using aproach I've mentioned (for performance reasons).

Schnur answered 14/11, 2011 at 20:14 Comment(4)
This does not answer the question. It's likely that the poster cannot change the signature of the native function.Serif
It does answer if he can, and it's really the easiest way in that case. There is no infomation in original answer whether he can or not.Higbee
I actually can change the signature, and this answer did prompt me to consider if the signature of the function is the best way to go. Although it doesn't answer the question I asked, it did help me in some way.Farman
ok, I give. However, I am unable to cancel my downvote unless this is edited.Serif

© 2022 - 2024 — McMap. All rights reserved.