【发布时间】:2026-01-11 14:15:01
【问题描述】:
这个问题是这个question的扩展。
我想为二维情况调整包装器。这是我的第一次尝试:
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;
}
PS:
原始的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)
制作:
r =
4 6
很遗憾,生成的 C 无法达到 Matlab 所能达到的效果(即返回一个数组):
__declspec(dllexport) real_T test(const emxArray_real_T *a);
real_T test(const emxArray_real_T *a)
{
real_T x;
int32_T k;
if (a->size[1] == 0) {
x = 0.0;
} else {
x = a->data[0];
for (k = 2; k <= a->size[1]; k++) {
x += a->data[k - 1];
}
}
return x;
}
【问题讨论】:
-
allocatedSize是元素的总数。所以*sizeof(double)是错误的。只需将其删除。将allocatedSize设置为data.GetLength(0) * data.GetLength(1)。主要问题是您不能将 double[,] blit 到 col 主要 MATLAB 数组上。我是正确的,这是正确的。一旦我知道了这一点,我就可以调整你的代码。 -
谢谢。我已经按照您的建议修改了代码。对于 new double[,] { { 1, 2, 4 }, { 1, 3, 4 } } 我得到 7 而不是 7 和 8。
标签: c# interop pinvoke matlab-coder