在pinvoke类/结构构造中使用MarshalAs而不是marshal

时间:2013-09-04 21:56:40

标签: c# c pinvoke marshalling

我有以下c#/ c代码,我在C dll中做的事情。我使用pinvoke / marshal作为黑魔法,使我能够在dll中动态分配/释放内容,而不需要c#代码知道任何不正常的事情。

在这个片段中,您将看到我使用两种不同的方式来分配/使用/释放双打数组。我的问题是,“MarshalAs(UnmanagedType ...”行)是做什么的,因为两个咒语(即使用或不使用MarshalAs语句)都能正常工作?我应该补充一点,我对C的理解很差,甚至更少理解C#,我理解整个pinvoke / marshal以及我理解的超对称量子力学。

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class row
    {
            public int a;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
            IntPtr[] b;

           IntPtr [] c; 
    } 

    // c code
struct row
{
    int a;
    double *b;
    double *c;
}

void fooe(void)
{
      row.b[4] = (double *) malloc(54000);
      row.c[4] = (double *) malloc(54000);
      free(row.b[4]);
      free(row.c[4]);
}

1 个答案:

答案 0 :(得分:-1)

ByValArray的这种特殊用法改变了一切。

首先,让我们考虑一下不ByValArray的情况。这里将数组编组为指向第一个元素的指针。匹配的C结构是

struct row
{
    int a;
    void* *b; // more likely you would use a typed pointer
    void* *c;
}

否则您使用ByValArray的情况。这里的数组是内联编组的,等效的C结构是:

struct row
{
    int a;
    void* b[12];
    void* *c;
}

这两个版本非常不同。

我也想知道你是否真的打算在C#代码中使用IntPtr[]。您是否真的想写double[]?所以,也许你的意思是:

[StructLayout(LayoutKind.Sequential)]
public class row
{
    public int a;
    double[] b;
    double[] c; 
} 

在这种情况下,匹配的C结构将是:

struct row
{
    int a;
    double *b;
    double *c;
}

我不知道fooe函数的含义是什么,但根本没有意义,也没有编译。看起来你正在尝试将指针指向一个毫无意义的双精度。