使用 P/Invoke C# 时如何用嵌套结构数组封送结构

问题描述 投票:0回答:1

我有以下 C 函数声明,我想从 C# 调用它(注意我无法访问 dll 的源代码):

int setData(OuterStruct *data);

该C函数的相关结构体如下:

typedef struct InnerStruct
{
    unsigned int a
    unsigned int b
    unsigned char *c
} InnerStruct;

typedef struct OuterStruct
{
    unsigned int d
    InnerStruct *e
} OuterStruct;

到目前为止我所做的是:

创建了我的托管结构变体

[StructLayout(LayoutKind.Sequential)]
public struct OuterStruct
{
    public uint d;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
    public InnerStruct[] e
}

[StructLayout(LayoutKind.Sequential)]
public struct InnerStruct
{
    public uint a;
    public uint b;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
    public byte[] c
}

创建了 DllImport 方法

[DllImport("myDll.dll", EntryPoint ="setData", CallingConvention= CallingConvention.StdCall]
public static extern int setData(ref OuterStruct data);

调用我的方法并最终得到一个常量“AccessViolationException”。目前,我不确定这是我这边的问题还是 .dll 的问题以及它如何处理输入,但想先解决我可能遇到的任何未解决的问题。

注意我已经为此 .dll 创建了多种其他使用简单结构的 P/Invoke 方法,只有这个失败了。此外,.dll 和 C# 项目都以 32 位运行

c# c pinvoke marshalling
1个回答
0
投票

你的声明不太正确:

  • c
    被声明为指针,因此您需要
    UnmanagedType.LPArray
    ,无论如何,这是默认值。
  • e
    被声明为指针,所以它也应该使用
    LPArray
    • 如果它实际上是单个对象而不是数组,那么
      InnerStruct
      需要是
      class
      并且声明应该是
      public InnerStruct e;
  • 数组大小的确切来源尚不清楚。
  • 也不清楚该参数在C端是否是
    const
    ,因此在C#端应该是
    [In] in
  • CallingConvention.StdCall
    可能是错误的:大多数 C 代码使用
    CallingConvention.Cdecl
[StructLayout(LayoutKind.Sequential)]
public struct OuterStruct
{
    public uint d;

    [MarshalAs(UnmanagedType.LPArray)]
    public InnerStruct[] e
}

[StructLayout(LayoutKind.Sequential)]
public struct InnerStruct
{
    public uint a;
    public uint b;
    [MarshalAs(UnmanagedType.LPArray)]
    public byte[] c
}
© www.soinside.com 2019 - 2024. All rights reserved.