C# 适用于二维情况的包装器类
这个问题是这个问题的延伸 我想调整包装的二维情况。这是我第一次尝试:C# 适用于二维情况的包装器类,c#,interop,pinvoke,matlab-coder,C#,Interop,Pinvoke,Matlab Coder,这个问题是这个问题的延伸 我想调整包装的二维情况。这是我第一次尝试: public class EmxArrayRealTWrapper : IDisposable { private readonly emxArray_real_T _value; private GCHandle _dataHandle; private GCHandle _sizeHandle; public emxArray_real_T Value { get { return _value; } } pu
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) * sizeof(double);
_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 [x] = test(a)
%#codegen
x = 0;
if(~isempty(coder.target))
assert(isa(a,'double'));
assert(all(size(a) == [1 Inf]));
end
x = sum(a);
a = [ 1 2; 3 4]
r = test(a)
public EmxArrayRealTWrapper(double[,] data)
{
int nRow = data.GetLength(0);
int nCol = data.GetLength(1);
double[] flattenedData = new double[nCol * nRow];
int index = 0;
for (int col=0; col<nCol; col++)
{
for (int row=0; row<nRow; row++)
{
flattenedData[index] = data[row, col];
index++;
}
}
_dataHandle = GCHandle.Alloc(flattenedData, GCHandleType.Pinned);
_value.data = _dataHandle.AddrOfPinnedObject();
_sizeHandle = GCHandle.Alloc(new int[] { nCol, nRow }, GCHandleType.Pinned);
_value.size = _sizeHandle.AddrOfPinnedObject();
_value.allocatedSize = nCol * nRow;
_value.numDimensions = 2;
_value.canFreeData = false;
}
可以这样调用:
function [x] = test(a)
%#codegen
x = 0;
if(~isempty(coder.target))
assert(isa(a,'double'));
assert(all(size(a) == [1 Inf]));
end
x = sum(a);
a = [ 1 2; 3 4]
r = test(a)
public EmxArrayRealTWrapper(double[,] data)
{
int nRow = data.GetLength(0);
int nCol = data.GetLength(1);
double[] flattenedData = new double[nCol * nRow];
int index = 0;
for (int col=0; col<nCol; col++)
{
for (int row=0; row<nRow; row++)
{
flattenedData[index] = data[row, col];
index++;
}
}
_dataHandle = GCHandle.Alloc(flattenedData, GCHandleType.Pinned);
_value.data = _dataHandle.AddrOfPinnedObject();
_sizeHandle = GCHandle.Alloc(new int[] { nCol, nRow }, GCHandleType.Pinned);
_value.size = _sizeHandle.AddrOfPinnedObject();
_value.allocatedSize = nCol * nRow;
_value.numDimensions = 2;
_value.canFreeData = false;
}
制作:
r =
4 6
不幸的是,生成的C无法实现Matlab可以实现的功能(即返回数组):
\u declspec(dllexport)实际测试(const emxArray\u real\u T*a);
实际测试(常数emxArray\u real\u T*a)
{
real_T x;
int32_T k;
如果(a->size[1]==0){
x=0.0;
}否则{
x=a->数据[0];
对于(k=2;k大小[1];k++){
x+=a->数据[k-1];
}
}
返回x;
}
我假设MATLAB数组结构使用col主顺序。在这种情况下,结构构造函数需要如下所示:
function [x] = test(a)
%#codegen
x = 0;
if(~isempty(coder.target))
assert(isa(a,'double'));
assert(all(size(a) == [1 Inf]));
end
x = sum(a);
a = [ 1 2; 3 4]
r = test(a)
public EmxArrayRealTWrapper(double[,] data)
{
int nRow = data.GetLength(0);
int nCol = data.GetLength(1);
double[] flattenedData = new double[nCol * nRow];
int index = 0;
for (int col=0; col<nCol; col++)
{
for (int row=0; row<nRow; row++)
{
flattenedData[index] = data[row, col];
index++;
}
}
_dataHandle = GCHandle.Alloc(flattenedData, GCHandleType.Pinned);
_value.data = _dataHandle.AddrOfPinnedObject();
_sizeHandle = GCHandle.Alloc(new int[] { nCol, nRow }, GCHandleType.Pinned);
_value.size = _sizeHandle.AddrOfPinnedObject();
_value.allocatedSize = nCol * nRow;
_value.numDimensions = 2;
_value.canFreeData = false;
}
请注意,这两个变体将数据传递给本机代码的方式不同。第一个版本传递原始数据的副本。第二个传递对原始数据的引用。我不确定您希望代码如何运行。修改第二个版本以传递副本非常容易。对于第一个版本,如果您希望本机代码修改数据并将这些修改反映回托管代码,那么您需要在本机调用返回后将修改封送回。
allocatedSize
是元素总数。因此,*sizeof(double)
是错误的。把它拿走。将allocatedSize
设置为data.GetLength(0)*data.GetLength(1)
。主要问题是不能将double[,]blit到一个数组上。我认为这是正确的。一旦我知道了,我就可以修改你的代码了。谢谢。我已经按照你的建议修改了代码。对于新的双[,]{{1,2,4},{1,3,4},我得到7,而不是7和8。谢谢。小错误。请使用;在nRowSo之后,是col专业还是row专业?我现在很好奇。我不得不说我有一些问题。我现在可以传递2d数组,但是返回值只是一个标量,matlab编码器只是生成这个签名。这对我来说还行,因为我可以传入一维非固定数组(即2d数组的第一列)并得到结果。您可以通过引用将空的emxArray\u real\T
作为参数传递。并使用它返回结果。或者您可以将emxArray\u real\u T*
作为函数返回值返回,并将其封送为IntPtr
。我对Matlab编码器了解不够,无法理解分配是如何工作的。另外,我非常想知道,col major还是row major?参见添加的C代码。我想是上校少校。现在试试你的建议。