这是对此问题的扩展返回一个数组,而不是一个标量.
This is an extension to this question to be able to return an array rather than a scalar.
现在看起来可以通过matlab编码器从matlab代码中生成C代码了(请参见下文).我只是试图弄清楚如何使结果返回C#世界.这是我的第一次尝试:
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#代码
[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:
考虑到大卫的回答,我目前正在尝试这样的事情:
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); }这仅给我一个条目:7 nCol和nRow等于1.
This only gives me one entry: 7 nCol and nRow are equal to 1.
推荐答案您实际上是在问如何将emxArray_real_T的内容读取到C#对象中.
You are essentially asking how to read the contents of a emxArray_real_T into a C# object.
让我们首先考虑一维数组.像这样阅读:
Let's first consider a 1D array. Read it like this:
emxArray_real_T result; // initialise this by your call to the native code int size = Marshal.ReadInt32(result.size); double[] data = new double[size]; Marshal.Copy(result.data, data, 0, size);就是这样.您想断言result.numDimensions == 1.
并且您可能不需要执行Marshal.Copy步骤.您可能仍然可以访问为result.data传递的数组,因此您可以使用它.
And you may not need to do the Marshal.Copy step. You probably still have access to the array you passed for result.data and so you can just use that.
二维情况几乎相同.再次,您需要检查result.numDimensions == 2.
The two dimensional case is just more of the same. Again you'll want to check that result.numDimensions == 2.
int[] size = new int[2]; Marshal.Copy(result.size, size, 0, 2); int nCol = size[0]; int nRow = size[1]; double[] data = new double[nCol * nRow]; Marshal.Copy(result.data, data, 0, nCol * nRow);这会将数据放入一维数组中,并且大概您希望将其放入二维托管数组中.假设MATLAB是col-major,则需要处理col-major到row-major的转换.
That puts the data in a one-dimensional array and presumably you'll want to put this into a two-dimensional managed array. Assuming the MATLAB is col-major, you'll need to deal with the col-major to row-major translation.
double[,] arr = new double[nRow, nCol]; int index = 0; for (int col = 0; col<nCol; col++) { for (int row = 0; row<nRow; row++) { array[row, col] = data[index]; index++; } }更多推荐
解组结果?
发布评论