Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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);
            }
        }
    }
}
share|improve this question

3 Answers 3

up vote 11 down vote accepted

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

share|improve this answer
    
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. –  Valdemar Nov 15 '11 at 0:06

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).

share|improve this answer
    
This does not answer the question. It's likely that the poster cannot change the signature of the native function. –  Odrade Nov 14 '11 at 21:34
    
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. –  Wisdom's Wind Nov 14 '11 at 21:51
    
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. –  Valdemar Nov 15 '11 at 0:04
    
ok, I give. However, I am unable to cancel my downvote unless this is edited. –  Odrade Nov 15 '11 at 0:43

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.