'C# how to get an array of int* from unmanaged C++
On the unmanaged side I have short* m_pLevels[4]
, I need to get this array of pointers to the C# side so I can then use each point to copy from the unmanaged side to a managed array.
How do I get an array of short*
to C# and would that array be an array of IntPtr
?
Solution 1:[1]
I recomend using C++/CLI to communicate between C# (managed) and C++ (native). In the examples below I used the simplest case where the native data is simply 1 binary buffer. You can adapt it to pass any form of native data.
You can take one of these 2 approches:
The most efficient is to pass the unmanaged data to C# and use it as is. You will have to use an
unsafe
methods to handle raw pointers. It's efficient but more risky. An example for an unsafe C# method getting a native buffer:unsafe void HandleNativeData(sbyte* pData, int dataLen) { ... }
The safest way is to marshal the unmanaged memory to managed one. If for example you have a C# or C++/CLI method that got a raw pointer from C++ (like in approach 1), you can do the following:
unsafe void HandleNativeData(sbyte* pData, int dataLen) { byte[] DataManagedBuf = new byte[dataLen]; Marshal.Copy((IntPtr)pData, DataManagedBuf, 0, dataLen); // At this point DataManagedBuf is a proper managed buffer, // containing the data that was passed from native C++. }
Solution 2:[2]
PInvoke is also an option:
// this function pre-supposes that everyone knows there are always
// exactly 4 buffers of data. that's pretty rare for IRL interop.
// normally you'd use a struct with fixed length arrays, but the
// question explicitly states short*[].
[DllImport("UnmanagedCode.dll", EntryPoint = "NameOfUnmanagedCodeFunction"]
private static extern void GetUnmanagedBuffers(IntPtr[] shortPtrs, int[] lengths);
// this function will call the unmanaged function and then
// marshal over the pointers into managed arrays
public List<short[]> GetBuffers()
{
var managedArrays = new List<short[]>(4);
// the unmanaged DLL fills in the buffer addresses for us
var shortPtrs = new IntPtr[4];
// and the lengths of each buffer
var lengths = new int[4];
GetUnmanagedBuffers(shortPtrs, lengths);
// input validation/exception handling omitted for brevity
for (int i = 0; i < 4; i++)
{
var length = bufferLengths[i];
// create the array and add it to the return values
managedArrays.Add(new short[length]);
// the overload of Marshal.Copy that works with int16[]
Marshal.Copy(bufferPtrs[i], //source pointer
managedArrays[i], //destination array
0, //starting index into dest
length) //number of int16 to copy
}
// often you'd see another PInvoke here telling the unmanaged
// code that you're done with the buffers so they can be freed.
return managedArrays;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |