C#中的C ++ Struct

我使用DllImport在我的C#项目中使用C ++编写的DLL,我使用的其中一个函数如下所示:

[DllImport("dds.dll", CharSet = CharSet.Auto)] private static extern int Par( ddTableResults2 tableResult, ref parResults ParResult, int vul ); 

parResults结构在C ++中定义如下:

 struct parResults { /* index = 0 is NS view and index = 1 is EW view. By 'view' is here meant which side that starts the bidding. */ char parScore[2][16]; char parContractsString[2][128]; }; 

C ++函数的开始

 int STDCALL Par(struct ddTableResults * tablep, struct parResults *presp, int vulnerable) 

我应该如何在C#中定义上述结构,以便能够将该结构作为en引用发送到DLL函数中?

这是我尝试但根本不工作,我只是得到访问冲突错误

  [StructLayout(LayoutKind.Sequential)] public struct parResults { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public char[,] parScore; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public char[,] parContractsString; public parResults(int x) { parScore = new char[2,16]; parContractsString = new char[2,128]; } } 

这在C#中编组是一个非常棘手的结构。 有多种方法可以尝试它,但我认为将字符数组表示为字节数组并手动编组字符串和字符串将是最干净的。 这是我的意思:

C ++

 #include  struct parResults { char parScore[2][16]; char parContractsString[2][128]; }; extern "C" { __declspec(dllexport) void foo(struct parResults *res) { strcpy(res->parScore[0], res->parContractsString[0]); strcpy(res->parScore[1], res->parContractsString[1]); } } 

C#

 using System; using System.Text; using System.Runtime.InteropServices; namespace ConsoleApplication1 { class Program { [StructLayout(LayoutKind.Sequential)] class parResults { private const int parScoreCount = 2; private const int parScoreLen = 16; private const int parContractsStringCount = 2; private const int parContractsStringLen = 128; [MarshalAs(UnmanagedType.ByValArray, SizeConst = parScoreCount * parScoreLen)] private byte[] parScoreBuff; [MarshalAs(UnmanagedType.ByValArray, SizeConst = parContractsStringCount * parContractsStringLen)] private byte[] parContractsStringBuff; public string getParScore(int index) { string str = Encoding.Default.GetString(parScoreBuff, index * parScoreLen, parScoreLen); int len = str.IndexOf('\0'); if (len != -1) str = str.Substring(0, len); return str; } public void setParScore(int index, string value) { byte[] bytes = Encoding.Default.GetBytes(value); int len = Math.Min(bytes.Length, parScoreLen); Array.Copy(bytes, 0, parScoreBuff, index * parScoreLen, len); Array.Clear(parScoreBuff, index * parScoreLen + len, parScoreLen - len); } public string parContractsString(int index) { string str = Encoding.Default.GetString(parContractsStringBuff, index * parContractsStringLen, parContractsStringLen); int len = str.IndexOf('\0'); if (len != -1) str = str.Substring(0, len); return str; } public void setParContractsString(int index, string value) { byte[] bytes = Encoding.Default.GetBytes(value); int len = Math.Min(bytes.Length, parContractsStringLen); Array.Copy(bytes, 0, parContractsStringBuff, index * parContractsStringLen, len); Array.Clear(parContractsStringBuff, index * parContractsStringLen + len, parContractsStringLen - len); } public parResults() { parScoreBuff = new byte[parScoreCount * parScoreLen]; parContractsStringBuff = new byte[parContractsStringCount * parContractsStringLen]; } }; [DllImport(@"...", CallingConvention = CallingConvention.Cdecl)] static extern void foo([In,Out] parResults res); static void Main(string[] args) { parResults res = new parResults(); res.setParContractsString(0, "foo"); res.setParContractsString(1, "bar"); foo(res); Console.WriteLine(res.getParScore(0)); Console.WriteLine(res.getParScore(1)); Console.ReadLine(); } } } 

在这里,我使用了一个类来表示结构。 由于C#中的类是引用,因此我们不会使用ref声明该类型的参数。 为了方便起见,我还使用了__cdecl ,以避免必须弄清楚函数的修饰名称。 但是你的库使用了__stdcall ,所以你需要坚持下去。

该课程演示了向两个方向发送数据。 如果数据流受到更多限制,您可以简化代码。