This is an extension to this question to be able to return an array rather than a scalar.
The produced C code from the matlab code via matlab coder looks ok now (see below). I just try to figure out how to get the results back into the C# world. Here is my first attempt:
C# code
[DllImport(@"C:\bla\CPlusPlus.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void test(ref emxArray_real_T a, ref emxArray_real_T result);
static void Main(string[] args)
{
double[,] array2D = new double[,] { { 1, 2, 4 }, { 1, 3, 4 } };
var wrapper = new EmxArrayRealTWrapper(array2D);
var t = wrapper.Value;
var t1 = wrapper.Value;
test(ref t, ref t1);
}
public class EmxArrayRealTWrapper : IDisposable
{
private readonly emxArray_real_T _value;
private GCHandle _dataHandle;
private GCHandle _sizeHandle;
public emxArray_real_T Value
{
get { return _value; }
}
public EmxArrayRealTWrapper(double[,] data)
{
_dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
_value.data = _dataHandle.AddrOfPinnedObject();
_sizeHandle = GCHandle.Alloc(new int[] { data.GetLength(0), data.GetLength(1) }, GCHandleType.Pinned);
_value.size = _sizeHandle.AddrOfPinnedObject();
_value.allocatedSize = data.GetLength(0) * data.GetLength(1);
_value.numDimensions = 2;
_value.canFreeData = false;
}
public void Dispose()
{
_dataHandle.Free();
_sizeHandle.Free();
GC.SuppressFinalize(this);
}
~EmxArrayRealTWrapper()
{
Dispose();
}
}
[StructLayout(LayoutKind.Sequential)]
public struct emxArray_real_T
{
public IntPtr data;
public IntPtr size;
public int allocatedSize;
public int numDimensions;
[MarshalAs(UnmanagedType.U1)]
public bool canFreeData;
}
Matlab code:
function [result] = test(a, result)
%#codegen
if(~isempty(coder.target))
assert(isa(a,'double'));
assert(all(size(a) == [1 Inf]));
assert(isa(result,'double'));
assert(all(size(result) == [1 Inf]));
end
result = sum(a);
produced C code
void test(const emxArray_real_T *a, emxArray_real_T *result)
{
real_T y;
int32_T k;
if (a->size[1] == 0) {
y = 0.0;
} else {
y = a->data[0];
for (k = 2; k <= a->size[1]; k++) {
y += a->data[k - 1];
}
}
k = result->size[0] * result->size[1];
result->size[0] = 1;
result->size[1] = 1;
emxEnsureCapacity((emxArray__common *)result, k, (int32_T)sizeof(real_T));
result->data[0] = y;
}
PS:
Given David's answer I am trying something like this at the moment:
[DllImport(@"C:\bla\CPlusPlus.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void test(ref emxArray_real_T a, ref emxArray_real_T result);
static void Main(string[] args)
{
double[,] array2D = new double[,] { { 1, 2, 4 }, { 1, 3, 4 } };
double[,] temp = new double[,] { { 0 }, { 0 } };
var wrapper = new EmxArrayRealTWrapper(array2D);
var wrapper1 = new EmxArrayRealTWrapper(temp);
var t = wrapper.Value;
var t1 = wrapper1.Value;
test(ref t, ref t1);
// initialise this by your call to the native code
int[] size = new int[2];
Marshal.Copy(t1.size, size, 0, 2);
int nCol = size[0];
int nRow = size[1];
double[] data = new double[nCol * nRow];
Marshal.Copy(t1.data, data, 0, nCol * nRow);
}
This only gives me one entry: 7 nCol and nRow are equal to 1.