在 pinvoke 类/结构构造中使用元帅与不使用元帅

本文关键字:pinvoke 结构 | 更新日期: 2023-09-27 18:30:23

我有以下 c#/c 代码,我在 C dll 中做事。 我使用 pinvoke/marshal 作为黑魔法,使我能够在 dll 中动态分配/释放内容,而无需 c# 代码知道发生了什么不幸的事情。

在此代码段中,您将看到我正在使用 2 种不同的方法来分配/使用/释放双精度数组。 我的问题是,"元帅(非托管类型)..."行,因为两个咒语(即使用或不使用元帅声明)都可以正常工作? 我应该补充一点,我对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]);
}

在 pinvoke 类/结构构造中使用元帅与不使用元帅

这种

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函数是什么意思,但它根本没有意义,也不会编译。看起来您正在尝试将指针分配给一个毫无意义的双精度。