I have a C# function that calls a C++ function to fill the array with pixel data from a camera. This is better than allocating memory on the C++ side and marshaling it on C# side each time the function is called.I thought about running into a scenario where a camera that outputs 720p can receive a command to output 1080p image. When this happens the array size allocated from C# may not be enough to hold the pixel information. That current function call will fail. I do not want to throw an exception and do not want it to fail. It must continue and should not discard that frame.My current solution is to check if the size of the pixels to write to the array is < the size of the array allocated from C# before writing to that array from C++ side. If the size of the pixels to write is bigger than the array, allocate new memory then return it to C#. After that resize the size of the array from C# then use Marshal.Copy to copy the data returned from C++ to that newly resized array in C#. Finally call a function from C++ side to free the memory allocated there.Bascially, when this problem happens, I will allocate memory on both sides (C++ and C#). How can this be improved?Note that I had to use unsafe and fixed keywords to pin the array for maximum performance after days of testing this with other methods. Anything faster than this is also acceptable.C++:int* test6FillArrayWithAutoResize(int* data, int count, int* outValue) {    //For testing Purposes. Used to determine how much size to write to the data variable    const int requiredMemory = 20;    //Create new and Resize if memory is not enough    if (requiredMemory > count) {        int* newVar = new int[requiredMemory];        //Do something to the variable then return it        for (int i = 0; i < requiredMemory; i++)        {            newVar[i] = i;        }        //Tell caller memory size        *outValue = requiredMemory;        //Return the new created variable        return newVar;    }    //Memory is enough. Write Directly to it the array that is passed in    for (int i = 0; i < count; i++)    {        data[i] = i;    }    //Tell caller memory size    *outValue = requiredMemory;    //Return null since the memory fits. No need to return pointer    return nullptr;}//Free memory allocated in the test6FillArrayWithAutoResize function abovevoid freeMem(int* data) {    if (data != nullptr)        delete[] data;}C#:[DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]private static extern IntPtr test6FillArrayWithAutoResize(IntPtr data, int count, ref int outValue);public unsafe int getTest6FillArrayWithAutoResize(ref int[] outArray, int count, ref int outValue){    IntPtr returnedPtr;    //Pin Memory    fixed (int* p = outArray)    {        IntPtr dataParam = (IntPtr)p;        returnedPtr = test6FillArrayWithAutoResize(dataParam, count, ref outValue);    }    //Resize outArray if outValue > count    if (outValue > count)    {        outArray = new int[outValue];        //Copy from result pointer to the C# variable        Marshal.Copy(returnedPtr, outArray, 0, 20);        //Free memory on the native sied        freeMem(returnedPtr);    }    return outValue;}[DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]private static extern void freeMem(IntPtr data);Test 1:const int arraySize = 44500;int[] arrayToFill = new int[arraySize];void Start(){    int length = arrayToFill.Length;    int outVal6 = 0;    int returnedSize = 0;    returnedSize = getTest6FillArrayWithAutoResize(ref arrayToFill, length, ref outVal6);}Result:Array is not resized because the required size is 20 but array size is 44500.Test 2:const int arraySize = 19;int[] arrayToFill = new int[arraySize];void Start(){    int length = arrayToFill.Length;    int outVal6 = 0;    int returnedSize = 0;    returnedSize = getTest6FillArrayWithAutoResize(ref arrayToFill, length, ref outVal6);}Result:Array is resized because the required size is 20 but array size is 19.Note:The required size is the requiredMemory variable defined in the C++ code. It is only there to emulate the behavior of the camera and for testing purposes. Also, forget about me using for loop to iterate through the array. This is only for testing purposes too. I plan to use std::copy for that so pretend that std::copy is used there. The thing I want to improve is how memory is allocated twice on both ends when size is not enough. Any other improvement is welcome.
C# to C++ function call that fills and auto resize array if size is not enough
c#;c++;memory management;unity3d;native code
Your situation immediately reminded me of the PC loser-ing problem: a classic case study contrasting the design philosophies of MIT's ITS operating system and the UNIX operating system developed at Bell Labs.Two famous people, one from MIT and another from Berkeley (but working  on Unix) once met to discuss operating system issues. The person from  MIT was knowledgeable about ITS (the MIT AI Lab operating system) and  had been reading the Unix sources. He was interested in how Unix  solved the PC loser-ing problem. The PC loser-ing problem occurs when  a user program invokes a system routine to perform a lengthy operation  that might have significant state, such as IO buffers. If an interrupt  occurs during the operation, the state of the user program must be  saved. Because the invocation of the system routine is usually a  single instruction, the PC of the user program does not adequately  capture the state of the process. The system routine must either back  out or press forward. The right thing is to back out and restore the  user program PC to the instruction that invoked the system routine so  that resumption of the user program after the interrupt, for example,  re-enters the system routine. It is called PC loser-ing because  the PC is being coerced into loser mode, where loser is the  affectionate name for user at MIT.The MIT guy did not see any code that handled this case and asked the  New Jersey guy how the problem was handled. The New Jersey guy said  that the Unix folks were aware of the problem, but the solution was  for the system routine to always finish, but sometimes an error code  would be returned that signaled that the system routine had failed to  complete its action. A correct user program, then, had to check the  error code to determine whether to simply try the system routine  again. The MIT guy did not like this solution because it was not the  right thing.The New Jersey guy said that the Unix solution was right because the  design philosophy of Unix was simplicity and that the right thing was  too complex. Besides, programmers could easily insert this extra test  and loop. The MIT guy pointed out that the implementation was simple  but the interface to the functionality was complex. The New Jersey guy  said that the right tradeoff has been selected in Unix-namely,  implementation simplicity was more important than interface  simplicity.Based on that lesson, I would seriously reconsider your design goal:I do not want to throw an exception and do not want it to fail. It must continue and should not discard that frame.Consider the consequences of that goal:You do the memory allocation in two ways: usually on the C# side, but sometimes on the C++ side.  That's two codepaths to maintain and test.If the C++ allocation mechanism worked well (reliably, maintainably, and fast), why wouldn't you use it as the sole solution?  As you stated, having C# be responsible for array allocation is simply better, except when there is insufficient capacity.I would also challenge your fear of discarding a frame.  You would have the same problem even if you were coding purely in C++.Here's a design that does all of the buffer allocation in C#.  The C++ function returns the size of the required buffer.  If your camera's API allows you to query the required frame size before retrieving the frame data, then the code could be even simpler than the solution below.C++:int testFillArray(int* data, int offset, int count) {    //For testing Purposes. Used to determine how much size to write to the data variable    const int requiredMemory = 20;    if (requiredMemory < count) {        count = requiredMemory;    }    for (int i = offset; i < offset + count; i++) {        data[i] = i;    }    return requiredMemory;}C#:public unsafe int getTestFillArray(ref int[] array){    int offset = 0, frameSize;    while (true)    {        fixed (int* p = array) // Pin memory        {            frameSize = offset + testFillArray((IntPtr)p, offset, array.Length - offset);        }        if (frameSize <= array.Length)        {            return frameSize;        }        // Insufficient buffer space.  Reallocate and retry.        var newArray = new int[frameSize];        Array.Copy(array, newArray, offset = array.Length);        array = newArray;    }}NitpicksIn your C++ code, in your //Memory is enough case, what happens if the camera produces less data than the array size?  You would write junk data at the end of the array.Use braces consistently.  In your C++ code, you used a different brace style for your if than for your loops.  You should also not omit optional braces, and if you must omit them, write the condition and statement on the same line.