c#编程指南(九) 平台调用P-INVOKE完全掌握,C#和C++互相调用

时间:2022-08-28 08:09:20

第一: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 }

 

 

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 }

 

 

 

第二: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 }

 

 

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 }

 

 

 

第三: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 }

 

 

 

 

c++:

 

 

  
  
  
1 typedef int ( __stdcall * FunctionPointerType1)( int i);
2
3   int SetFunctionPointer(FunctionPointerType1 pointer)
4 {
5 return pointer( 1 );
6 }

 

 

微软很牛逼,基本上C#和C++互相调用完全没有问题,只要注意参数的Marshar和调用协议就可以了。

 

下载:代码