C#在和C++进行交互时,有时候会需要传递结构体。
做一些总结,避免大家在用的时候踩坑。
一般情况
例如我们在C++里定义了一个struct_basic结构体
1 struct struct_basic
2 {
3 WORD value_1;
4 LONG value_2;
5 DWORD value_3;
6 UINT value_4;
7 BOOL value_5;
8 };
这种情况在C#里调用,只需要注意数据类型对应就行了
在C#里定义如下
1 struct struct_basic
2 {
3 public ushort value_1;
4 public int value_2;
5 public uint value_3;
6 public uint value_4;
7 public bool value_5;
8 }
使用导出函数来测试一下
1 extern "C" __declspec(dllexport) void get_basic(struct_basic basic);
2
3 extern "C" __declspec(dllexport) void get_basic(struct_basic basic)
4 {
5 basic.value_1 = 1;
6 basic.value_2 = 2;
7 basic.value_3 = 3;
8 basic.value_4 = 4;
9 basic.value_5 = FALSE;
10 }
在C#中调用
[DllImport("lib.dll")]
public static extern void get_basic(ref struct_basic basic);
static void Main(string[] args)
{
struct_basic basic = new struct_basic();
get_basic(ref basic);
Console.WriteLine($"{basic.value_1} {basic.value_2} {basic.value_3} {basic.value_4} {basic.value_5}");
}
输出结果如下:
包含字符串的情况
C++
1 struct struct_advanced
2 {
3 WORD id;
4 CHAR message[256];
5 };
这种需要使用MarshalAsAttribute特性来指示如何在托管代码与非托管代码之间封送数据。
UnmanagedType.ByValTStr表示 结构中大小固定的字符串
SizeConst可以指定字符数组的大小
说明:
如果未指定CharSet,默认使用的是Ansi(char)。
Unicode为w_char。
C#
1 [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
2 struct struct_advanced
3 {
4 public ushort id;
5
6 [MarshalAs(UnmanagedType.ByValTStr,SizeConst =256)]
7 public string message;
8 };
使用导出函数测试
C++
1 extern "C" __declspec(dllexport) void get_advanced(struct_advanced* advanced);
2
3 extern "C" __declspec(dllexport) void get_advanced(struct_advanced* advanced)
4 {
5 advanced->id = 101;
6 lstrcpyW(advanced->message, L"HelloWorld");
7 }
在C#中调用
1 class Program
2 {
3 [DllImport("lib.dll")]
4 public static extern void get_advanced(ref struct_advanced advanced);
5
6 static void Main(string[] args)
7 {
8 struct_advanced advanced = new struct_advanced();
9 get_advanced(ref advanced);
10 Console.WriteLine($"{advanced.id} {advanced.message}");
11 }
12 }
输出结果: