0

このC#構造体の「コンストラクター」を作成しようとしています(最初の試行が含まれています)。

[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;

public emxArray_real_T(double[] cSharpData)
{
    var arraySize = Marshal.SizeOf(cSharpData[0]) * cSharpData.Length;
    this.data = Marshal.AllocHGlobal(arraySize);
    // ????
    numDimensions = 1;
    canFreeData = false;
}
}

Cに対応するC構造体は次のようになります。

typedef struct emxArray_real_T
{
   real_T *data;
   int32_T *size;
   int32_T allocated;
   int32_T numDimensions;
   boolean_T canFreeData;
} emxArray_real_T;

ここで説明します。

コメント/回答を楽しみにしています。ありがとう!

4

2 に答える 2

1

これを行う方法については、いくつかの選択肢があります。アンマネージメモリを割り当てることができます。次に、管理対象メモリの内容をコピーします。そして、おそらくネイティブコードへの呼び出しが戻ったときにそれをコピーして戻します。

あなたの例はそれから設定canFreeDataされているのでfalse、私はあなたがそれを他の方法でやりたいと思うと思います。そしてそれは、管理されたメモリをネイティブコードに渡すことです。そのためには、GCの動きから保護するためにピンで留める必要があります。

これらのアプローチのいずれかを機能させるには、ネイティブメモリまたはピン留めのいずれかを管理するラッパークラスが必要だと思います。固定アプローチに取り組む方法は次のとおりです。

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

public class emxArray_real_T_Wrapper : IDisposable
{
    private emxArray_real_T value;
    private GCHandle dataHandle;
    private GCHandle sizeHandle;

    public emxArray_real_T Value {
        get { return value; } 
    }

    public emxArray_real_T_Wrapper(double[] data)
    {
        dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
        value.data = dataHandle.AddrOfPinnedObject();
        sizeHandle = GCHandle.Alloc(new int[] { data.Length }, GCHandleType.Pinned);
        value.size = sizeHandle.AddrOfPinnedObject();
        value.allocatedSize = data.Length;
        value.numDimensions = 1;
        value.canFreeData = false;
    }

    public void Dispose()
    {
        dataHandle.Free();
        sizeHandle.Free();
        GC.SuppressFinalize(this);
    }

    ~emxArray_real_T_Wrapper()
    {
        Dispose();
    }
}
于 2013-02-22T13:04:29.033 に答える
1

コード:

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

public class emxArray_real_T_Wrapper : IDisposable
{
    private emxArray_real_T value;
    private GCHandle dataHandle;
    private GCHandle sizeHandle;

    public ref emxArray_real_T Value
    {
        get { return ref value; }
    }

    public double[] Data
    {
        get
        {
            double[] data = new double[value.allocatedSize];
            Marshal.Copy(value.data, data, 0, value.allocatedSize);
            return data;
        }
    }

    public emxArray_real_T_Wrapper(double[] data)
    {
        dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
        value.data = dataHandle.AddrOfPinnedObject();
        sizeHandle = GCHandle.Alloc(new int[] { 1, data.Length }, GCHandleType.Pinned);
        value.size = sizeHandle.AddrOfPinnedObject();
        value.allocatedSize = data.Length;
        value.numDimensions = 1;
        value.canFreeData = false;
    }

    public void Dispose()
    {
        dataHandle.Free();
        sizeHandle.Free();
        GC.SuppressFinalize(this);
    }

    ~emxArray_real_T_Wrapper()
    {
        Dispose();
    }

宣言:

[DllImport("TestFunc.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void TestFunc(int n, double WnLow, double WnHigh, ref emxArray_real_T kernel);

それを使用する:

public double[] CalculateBandPassCoefficients(int order, double FreqCutoffNormLow, double FreqCutoffNormHigh)
{
    double[] kernel = new double[order];
    using (emxArray_real_T_Wrapper wb = new emxArray_real_T_Wrapper(kernel))
    {
        TestFunc(order, FreqCutoffNormLow, FreqCutoffNormHigh, ref kernelWrapper.Value);

        kernel = kernelWrapper.Data;
    }
    return kernel;
}
于 2019-04-18T12:38:14.917 に答える