去编组结果?
Posted
技术标签:
【中文标题】去编组结果?【英文标题】:de-marshal results? 【发布时间】:2013-02-23 17:15:01 【问题描述】:这是question 的扩展,能够返回数组而不是标量。
通过 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。
【问题讨论】:
t1 可能指向同一个内存,所以上面的方法可能行不通,但这是第一次尝试。 很抱歉我看不到... 【参考方案1】:您实际上是在问如何将emxArray_real_T
的内容读入 C# 对象。
让我们首先考虑一个一维数组。像这样阅读它:
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
传递的数组,因此您可以使用它。
二维情况更是如此。您需要再次检查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 的转换。
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++;
【讨论】:
对不起,我不明白。我尝试实施您的建议 - 请参阅 PS 原始问题。 您需要更加努力地了解这里发生了什么。我认为您希望我们在您不了解任何内容的情况下解决您的问题。当然 nrow 和 ncol 都是 1。当然只返回一个值。这就是本机代码返回的内容。它就在您问题的代码中。答案中的代码是准确的。您可以从这个答案和我对您问题的其他答案中获得所需的一切。如果您仍然卡住,您需要了解有关 Matlab 数组存储的更多信息。 我唯一不确定的是数据是 col 主要还是 row 主要。以及值出现在大小数组中的顺序。您应该能够从文档中解决这个问题。但是,我想知道您是否理解 col major 和 row major 的含义。 嗯,nrow 和 ncol 不应该同时是一个。给定: double[,] array2D = new double[,] 1, 2, 4 , 1, 3, 4 ; (用 C# 说话)我希望 nrow 或 ncol 为 2。结果应该是 7 和 8 - 一行和两列或其他。如果我给人的印象是我希望你解决我的问题,我很抱歉。这不是我的本意!可能是我遗漏了一些东西 - 抱歉,这一天很长...... 您问题中生成的 C 代码非常清楚地将 nRow 和 nCol 都设置为 1。以上是关于去编组结果?的主要内容,如果未能解决你的问题,请参考以下文章