Marshal一个嵌入在结构中的可变大小的结构数组

时间:2014-03-28 19:15:11

标签: c# c pinvoke marshalling

我需要在编译时传递一个包含结构数组的结构,这些结构的长度是未知的。

我找到了如何使用IntPtr []数组和Marshal.StructureToPtr使用Marshal.Copy和固定大小的结构数组来制作可变大小的基元数组的示例,但是它使用了MarshalAs(UnamangedType.ByValArray)结构定义需要SizeConst参数。

以下是我正在尝试做的一个示例。在C dll中,我有一个具有正弦波定义的结构

typedef struct sinWave
{
    double amp;         /*  sine wave amplitude     */
    double t;           /*  time                    */
    double period;      /*  oscilation period       */
    double omega;       /*  phase angle             */
} sinWave;

和一个可以容纳多个波浪的结构

typedef struct sinWaveAdd
{
    sinWave *waves;     /*  array of sine waves     */
    int len;            /*  length of the array     */
} sinWaveAdd;

使用以下原型

在波叠加函数中使用
__declspec( dllexport ) double calculateMult( sinWaveAdd *in )

在c#中,我有一个sinWave结构,它可以自行运行

[StructLayout(LayoutKind.Sequential)]
public class sinWaveStruct
{
    public double amp;      /*  sine wave amplitude */
    public double t;        /*  time                */
    public double period;   /*  oscillation period  */
    public double omega;    /*  phase angle         */
}

public sinWaveStruct(double ampP, double tP, double periodP, double omegaP)
{
    amp = ampP;
    t = tP;
    period = periodP;
    omega = omegaP;
}
}

但我真的不知道如何构建更大的结构

[StructLayout(LayoutKind.Sequential)]
public class sinWaveAddClass
{
    public IntPtr waves;        /*  array of sinWaveStruct waves    */
    public int len;             /*  length of array */
}

因为我需要波数不恒定。

有没有办法将wave数组分支到sinWaveStruct [],IntPtr或IntPtr []而没有一个恒定大小的数组?

1 个答案:

答案 0 :(得分:1)

我将结构声明为struct。这使得它们成为值类型而不是引用类型。当你想要制作它们的数组时很重要。尤其是sinWave是blittable。

public struct sinWaveStruct
{
    public double amp;      /*  sine wave amplitude */
    public double t;        /*  time                */
    public double period;   /*  oscillation period  */
    public double omega;    /*  phase angle         */
}

public struct sinWaveAdd
{
    public IntPtr waves;        /*  array of sinWaveStruct waves    */
    public int len;             /*  length of array */
}

您导入的功能是:

[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
public static extern double calculateMult(ref sinWaveAdd in);

然后创建并填充sinWaveAdd

的数组
sinWaveStruct[] arr = new sinWaveStruct[len];
// populate arr

然后固定数组并获取其地址:

GCHandle arrHandle = GCHandle.Alloc(arr, GCHandleType.Pinned);
try
{
    sinWaveAdd in;
    in.waves = arrHandle.AddrOfPinnedObject();
    in.len = len;
    double retval = calculateMult(ref in);
}
finally
{
    arrHandle.Free();
}