-2

After reading multiple post on SO, I need to pre-allocate my memory buffer on the C# side, pass it to the native side so when the function returns the value in the memory buffer will be properly filled (this avoid multiple copies of the data).

See:

Which does basically:

[DllImport("NativePlugin", CallingConvention = CallingConvention.Cdecl)]
private static extern void fillArrayNative(IntPtr data, int count, out int outValue);

public unsafe void getFillArrayNative(float[] outArray, int count, out int outValue)
{
    //Pin Memory
    fixed (float* p = outArray)
    {
        fillArrayNative((IntPtr)p, count, out outValue);
    }
}

How can I make sure this function will be thread-safe ? The point here is that the same buffer outArray should be used as I iterate over each files and populate the outArray.

malat
  • 12,152
  • 13
  • 89
  • 158
  • I do not know enough about the c++ code. One of two things are happening 1) You are allocating memory in your code before calling the c++ code. Use following : https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.allochglobal?view=net-5.0 2) The c++ code is allocating the memory using Window Allocation method. The IntPtr is the pointer to the Windows buffer and you have to deallocate the memory to prevent a memory leak. To get data you need https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.ptrtostructure?view=net-5.0 – jdweng Apr 27 '21 at 07:24
  • The whole point is that memory allocation is done on C# side (not on C++ side). – malat Apr 27 '21 at 07:25
  • Sounds like you need some kind of inter-process synchronization. Named mutexes is what comes first in mind. – Sinatr Apr 27 '21 at 07:29
  • Regarding IPC for .net core see [this topic](https://stackoverflow.com/q/58549763/1997232). You will need something multi-platform and multi-language (c# and c++ ?). – Sinatr Apr 27 '21 at 07:38
  • You can declare your fillArrayNative like this: `void fillArrayNative([In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] float[] data, int count, out int outValue)`, which avoids unsafe, allocating, copying (unless you really want to do this). As for threading, there's nothing to say with p/invoke. .NET brings nothing specific to the table, no synchronization, lock, etc, so it's up to you to make sure it works in your context. – Simon Mourier Apr 27 '21 at 07:38
  • I said I didn't know enough about the c++ code.I don't see any memory allocation in posted code. I just see bytes being cast. – jdweng Apr 27 '21 at 08:11

1 Answers1

0

How can I make sure this function will be thread-safe ?

The same way you make sure every other function is threadsafe.

While fillArrayNative is running it presumably have exclusive accesses to the array. If the method uses threads internally it is up to the method itself to perform any necessary synchronization.

Once fillArrayNative returns it presumably does not access the array anymore. If it does save the pointer for later use you will have more than threading problems. After the fixed statement ends the array may be moved by the garbage collector, and accessing the pointer after that point will be unpredictable, but probably very bad.

If you intend to to update the array at the same time you read it, then a simple array is simply not appropriate. Bu the question lack sufficient information to suggest the best approach for this scenario.

JonasH
  • 28,608
  • 2
  • 10
  • 23