这篇是讲述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);
|
请发表评论