我有以下 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
被声明为指针,因此您需要 UnmanagedType.LPArray
,无论如何,这是默认值。e
被声明为指针,所以它也应该使用LPArray
。
InnerStruct
需要是 class
并且声明应该是 public InnerStruct e;
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
}