c#编程指南(九) 平台调用P-INVOKE完全掌握,C#和C++互相调用
c#编程指南(九) 平台调用P-INVOKE完全掌握,C#和C++互相调用
第一:C# 调用C++,使用P-INVOKE技术调用C++编写的动态链接库。而动态链接库导出的一般有两种调用协议,__stdcall和_cdecl。下面展示调用两种不同调用协议的方法:
C++:
1 int __stdcall Test1(int i)
2 {
3 return printf("The __stdcall invoke convesion:%d\n", i);
4 }
5
6 int _cdecl Test2(int i)
7 {
8 return printf("The _cdecl invoke convesion:%d\n", i);
9 }
2 {
3 return printf("The __stdcall invoke convesion:%d\n", i);
4 }
5
6 int _cdecl Test2(int i)
7 {
8 return printf("The _cdecl invoke convesion:%d\n", i);
9 }
c#:
1 [DllImport("TestDll", CallingConvention = CallingConvention.StdCall)]
2 public static extern int Test1(int i);
3
4 [DllImport("TestDll",CallingConvention= CallingConvention.Cdecl)]
5 public static extern int Test2(int i);
6
7 public void Run()
8 {
9 ...
10 Test1(20);
11 Test2(30);
12 ...
13 }
2 public static extern int Test1(int i);
3
4 [DllImport("TestDll",CallingConvention= CallingConvention.Cdecl)]
5 public static extern int Test2(int i);
6
7 public void Run()
8 {
9 ...
10 Test1(20);
11 Test2(30);
12 ...
13 }
第二:C#调用C++代码,也可以间接的使用C++的函数指针。(强烈建议不要使用此方法)
c++:
1 typedef int ( __stdcall * FunctionPointerType1)(int i);
2 typedef int ( __cdecl * FunctionPointerType2)(int i);
3
4 int __stdcall Test1(int i)
5 {
6 return printf("The __stdcall invoke convesion:%d\n", i);
7 }
8
9 int _cdecl Test2(int i)
10 {
11 return printf("The _cdecl invoke convesion:%d\n", i);
12 }
13
14 FunctionPointerType1 GetFunctionPointer1(int i)
15 {
16 return Test1;
17 }
18
19 FunctionPointerType2 GetFunctionPointer2(int i)
20 {
21 return Test2;
22 }
2 typedef int ( __cdecl * FunctionPointerType2)(int i);
3
4 int __stdcall Test1(int i)
5 {
6 return printf("The __stdcall invoke convesion:%d\n", i);
7 }
8
9 int _cdecl Test2(int i)
10 {
11 return printf("The _cdecl invoke convesion:%d\n", i);
12 }
13
14 FunctionPointerType1 GetFunctionPointer1(int i)
15 {
16 return Test1;
17 }
18
19 FunctionPointerType2 GetFunctionPointer2(int i)
20 {
21 return Test2;
22 }
C#:
1 [DllImport("TestDll")]
2 public static extern FunctionPointerType GetFunctionPointer1(int i);
3
4 [DllImport("TestDll")]
5 [return:MarshalAs(UnmanagedType.FunctionPtr)]
6 public static extern FunctionPointerType GetFunctionPointer2(int i);
7
8 public void Run()
9 {
10 ...
11 FunctionPointerType func1 = GetFunctionPointer1(0);
12 FunctionPointerType func2 = GetFunctionPointer2(0);
13 //实验证明无论__stdcall和_cdecl函数指针C#都可以正常调用,
14 //具体内部不知道微软如何做的,高手指教了。
15 func1(40);
16 func2(50);
17 ...
18 }
2 public static extern FunctionPointerType GetFunctionPointer1(int i);
3
4 [DllImport("TestDll")]
5 [return:MarshalAs(UnmanagedType.FunctionPtr)]
6 public static extern FunctionPointerType GetFunctionPointer2(int i);
7
8 public void Run()
9 {
10 ...
11 FunctionPointerType func1 = GetFunctionPointer1(0);
12 FunctionPointerType func2 = GetFunctionPointer2(0);
13 //实验证明无论__stdcall和_cdecl函数指针C#都可以正常调用,
14 //具体内部不知道微软如何做的,高手指教了。
15 func1(40);
16 func2(50);
17 ...
18 }
第三:C++调用C#函数,C#定义方法和方法的委托。传递委托给C++函数,.NET Framework会自动把委托转化成函数指针,对应的C++函数指针类型只能是__stdcall调用协议的,因为C#的方法默认编程成这个调用协议的,然后使用C++函数指针调用即可。
c#:
1 public delegate int FunctionPointerType(int i);
2
3 [DllImport("TestDll")]
4 public static extern int SetFunctionPointer(FunctionPointerType pointer);
5
6 FunctionPointerType test1 = delegate(int i) { Console.WriteLine("The C# Anonymous Method :" + i); return 0; };
7
8 public int CSharpTest1(int i)
9 {
10 Console.WriteLine("The C# member Method :" + i);
11 return 0;
12 }
13
14 public static int CSharpTest2(int i)
15 {
16 Console.WriteLine("The C# class Method :" + i);
17 return 0;
18 }
19
20 public void Run()
21 {
22 ...
23 FunctionPointerType test2 = CSharpTest1;
24 FunctionPointerType test3 = CSharpTest2;
25 SetFunctionPointer(test1);
26 SetFunctionPointer(test2);
27 SetFunctionPointer(test3);
28 ...
29 }
2
3 [DllImport("TestDll")]
4 public static extern int SetFunctionPointer(FunctionPointerType pointer);
5
6 FunctionPointerType test1 = delegate(int i) { Console.WriteLine("The C# Anonymous Method :" + i); return 0; };
7
8 public int CSharpTest1(int i)
9 {
10 Console.WriteLine("The C# member Method :" + i);
11 return 0;
12 }
13
14 public static int CSharpTest2(int i)
15 {
16 Console.WriteLine("The C# class Method :" + i);
17 return 0;
18 }
19
20 public void Run()
21 {
22 ...
23 FunctionPointerType test2 = CSharpTest1;
24 FunctionPointerType test3 = CSharpTest2;
25 SetFunctionPointer(test1);
26 SetFunctionPointer(test2);
27 SetFunctionPointer(test3);
28 ...
29 }
c++:
1 typedef int ( __stdcall * FunctionPointerType1)(int i);
2
3 int SetFunctionPointer(FunctionPointerType1 pointer)
4 {
5 return pointer(1);
6 }
2
3 int SetFunctionPointer(FunctionPointerType1 pointer)
4 {
5 return pointer(1);
6 }
微软很牛逼,基本上C#和C++互相调用完全没有问题,只要注意参数的Marshar和调用协议就可以了。