C#调用C++数组,结构体DLL
1.基本数据类型的传递
常见数据类型的传递
C/C++ |
C# |
长度 |
short |
short |
2Bytes |
int |
int |
4Bytes |
long(该类型在传递的时候常常会弄混) |
int |
4Bytes |
bool |
bool |
1Byte |
char(Ascii码字符) |
byte |
1Byte |
wchar_t(Unicode字符,该类型与C#中的Char兼容) |
char |
2Bytes |
float |
float |
4Bytes |
double |
double |
8Bytes |
C++传入、传出C#数组都可以实现,传入数组直接传入,传出数组需要用指针传出。
(1).C++传入数组(测试1加到9的和)
.cpp文件 extern "C" __declspec(dllexport) void test(const int N, const int n[], int& Z) { for (int i = 0; i<N; i++) { Z += n[i]; } }
.cs文件 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; namespace Application6 { class Program { [DllImport(@"C:\Users\wdy\Documents\visual studio 2013\Projects\Application5\Debug\Application5.dll", EntryPoint = "test", CallingConvention = CallingConvention.Cdecl)] public static extern double test(int N, int[] n, ref int Z); static void Main(string[] args) { int N = 0; int[] n; n = new int[10]; for (int i = 0; i < 10; i++) { n[i] = i; } test(n.Length, n, ref N); Console.WriteLine(N.ToString()); Console.Read(); } } }
结果:
(2).C++传出数组(测试传出结构体数组指针字符串)
.cpp文件 #include "stdafx.h" #include "Application3.h" struct cmppe_submit { char user[10][200]; }; extern "C" __declspec(dllexport) void GetUser(cmppe_submit* lpSubit) { strcpy(lpSubit->user[0], "waqerqwdsewf"); }
.cs文件 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; namespace Application4 { class Program { struct cmppe_submit { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2000)] public byte[] dst_addr; } [DllImport(@"C:\users\wdy\documents\visual studio 2013\Projects\Application3\Debug\Application3.dll", EntryPoint = "GetUser", CallingConvention = CallingConvention.Cdecl)] private extern static void GetUser(ref cmppe_submit lpSubmit);//用ref声明结构 static void Main(string[] args) { cmppe_submit submit; submit.dst_addr = new byte[2000]; GetUser(ref submit); string str = System.Text.Encoding.Default.GetString(submit.dst_addr, 0, 25); Console.WriteLine(str); Console.Read(); } } }
调试中出现过的Bug:
.Program::GetUser”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。
添加属性:EntryPoint = "GetUser", CallingConvention = CallingConvention.Cdecl
结果:
(3)C++传入、传出带参数结构体
.h文件 #define TESTCPPDLL_API __declspec(dllexport) struct Vector3 { float X, Y, Z; }; EXTERN_C TESTCPPDLL_API void __stdcall SendStructFromCSToCPP(Vector3 vector);
.cpp文件 TESTCPPDLL_API void __stdcall SendStructFromCSToCPP(Vector3 vector) { vector.X = vector.X + 10; cout << "got vector3 in cpp,x:"; cout << vector.X+10; cout << ",Y:"; cout << vector.Y; cout << ",Z:"; cout << vector.Z; }
.CS文件 [StructLayout(LayoutKind.Sequential)] struct Vector3 { public float X, Y, Z; } [DllImport(@"C:\Users\wdy\Documents\visual studio 2013\Projects\TestCPPDLL\x64\Debug\TestCPPDLL.dll", EntryPoint = "SendStructFromCSToCPP")] extern static void SendStructFromCSToCPP(Vector3 vector); Vector3 vector = new Vector3() { X = 10, Y = 20, Z = 30 }; //将vector传递给C++并在C++中输出 SendStructFromCSToCPP(vector);
结果:
赌上我的人生为梦想,即使是臭名远扬,也要我的名字响彻天堂