这是对这个问题的扩展,能够返回一个数组而不是一个标量。
通过 matlab 编码器从 matlab 代码生成的 C 代码现在看起来没问题(见下文)。我只是想弄清楚如何将结果返回到 C# 世界。这是我的第一次尝试:
C# 代码
[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代码:
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);
生成的C代码
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:
鉴于大卫的回答,我目前正在尝试这样的事情:
[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);
}
这只给了我一个条目:7 nCol 和 nRow 等于 1。