解组结果? [英] de-marshal results?

查看:90
本文介绍了解组结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是对此问题的扩展返回一个数组,而不是一个标量.

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++;
    }
}

这篇关于解组结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆