现在的位置: 首页 > 综合 > 正文

c#编程指南(十一) 平台调用P-INVOKE完全掌握, 指针大全

2012年06月06日 ⁄ 综合 ⁄ 共 3155字 ⁄ 字号 评论关闭

这篇是讲述P-INVOKE中,应对各种指针的方法。包括普通指针,字符串指针,二级指针,指针数组,函数指针,结构体指针。篇幅估计有点长,大家耐心点看。嘿嘿~~

 

第一:普通指针,包括char *,short *,int *,__int64 *,这些指针进行平台调用是都对应C#的IntPtr类型,然后使用Marshal.ReadXXX()系列函数读取就可,写内存时使用Marshal.WriteXXX()系列函数就行。

 

c++:


28  static int test5 = 100;
29  int * __stdcall ReadInt()
30 {
31 return &test5;
32 }

 

c#:注意Marshal.ReadXXX()系列函数的使用


15 [DllImport("TestDll")]
16 public static extern IntPtr ReadInt();
29 //##############################
42 IntPtr p5 = ReadInt();
43 Console.WriteLine(Marshal.ReadInt32(p5));
44 IntPtr p6 = ReadUint();
45 Console.WriteLine(Convert.ToUInt32(Marshal.ReadInt32(p6)));

 

 

第二:字符串指针上一篇已经有过讨论,可以使用marshalAs返回值,当然也可以用Marshal.PtrToStringAuto()来读取字符串。个人推荐第一个。

 

c++:

1 static char * test9 = "you are very very bad bad girl, gaga!";
2  char * __stdcall ReadString()
3 {
4 return test9;
5 }
6
7
8  static wchar_t * test10 = TEXT("you are very very bad bad girl, gaga!");
9 wchar_t * __stdcall ReadStringW()
10 {
11 return test10;
12 }

 

c#:注意Marshal.PtrToStringAuto()函数的使用。

1 [DllImport("TestDll")]
2 [return: MarshalAs(UnmanagedType.LPStr)]
3 public static extern string ReadString();
4
5 [DllImport("TestDll")]
6 public static extern IntPtr ReadStringW();
7 //#########################
8 Console.WriteLine(ReadString());
9
10 IntPtr p9 = ReadStringW();
11 Console.WriteLine(Marshal.PtrToStringAuto(p9));

 

 

第三:函数指针,C#的委托就对应C++的__stdcall调用协议的函数指针。前面也有讨论。

c++:

1 typedef void (__stdcall * FunctionPoint)(void);
2 void __stdcall TestFunction(){printf("you are very very bad bad girl, gaga!\n");}
3 FunctionPoint __stdcall GetFunctionPointer()
4 {
5 return TestFunction;
6 }

 

c#:

1 public delegate void FunctionPointer();
2 [DllImport("TestDll")]
3 public static extern FunctionPointer GetFunctionPointer();
4 //#########################
5 FunctionPointer pointer = GetFunctionPointer();
6 pointer();

 

 

第四:指针的指针,也就是二级指针,要使用Marshal.ReadIntPtr()来读取。

c++:

1 static int test11 = 555;
2 static int * test12 = &test11;
3 int ** __stdcall ReadPoint2()
4 {
5 return &test12;
6 }

 

c#:

1 [DllImport("TestDll")]
2 public static extern IntPtr ReadPoint2();
3 //#########################
4 IntPtr p10 = ReadPoint2();
5 IntPtr p11 = Marshal.ReadIntPtr(p10);
6 int test10 = Marshal.ReadInt32(p11);
7 Console.WriteLine(test10);

 

第五:指针数组没有太直接的方法,因为C++所有指针都是4BYTE所以这里我是这么读的。

C++:

1 static int test13 = 666;
2 static int test14 = 777;
3 static int * test15[3] = {0};
4 int ** __stdcall ReadPointArray()
5 {
6 test15[0] = &test11;
7 test15[1] = &test13;
8 test15[2] = &test14;
9 return test15;
10 }

 

C#:

1 [DllImport("TestDll")]
2 public static extern IntPtr ReadPointArray();
3 //#########################
4 IntPtr p12 = ReadPointArray();
5 int test11 = p12.ToInt32();
6 Console.WriteLine(Marshal.ReadInt32(Marshal.ReadIntPtr(p12)));
7 Console.WriteLine(Marshal.ReadInt32(Marshal.ReadIntPtr(new IntPtr(test11 + 0))));
8 Console.WriteLine(Marshal.ReadInt32(Marshal.ReadIntPtr(new IntPtr(test11 + 4))));
9 Console.WriteLine(Marshal.ReadInt32(Marshal.ReadIntPtr(new IntPtr(test11 + 8))));

 

 

最后: 结构体的指针,用C#建立对应C++的结构体,并使用   [StructLayout(LayoutKind.Sequential)]属性,

使用Marshal.PtrToStructure()读取。

c++:

1 struct Test
2 {
3 int test;
4 };
5
6 static Test test16;
7 Test * __stdcall ReadStruct()
8 {
9 test16.test = 1234;
10 return &test16;
11 }

 

c#:

1 [StructLayout(LayoutKind.Sequential)]
2 public struct Test
3 {
4 public int test;
5 }
6
7 [DllImport("TestDll")]
8 public static extern IntPtr ReadStruct();
9 //#########################
10
11 IntPtr p13 = ReadStruct();
12 Test test13 = (Test)Marshal.PtrToStructure(p13,typeof(Test));
13 Console.WriteLine(test13.test);

 

抱歉!评论已关闭.