抑郁症健康,内容丰富有趣,生活中的好帮手!
抑郁症健康 > c#编程指南(十) 平台调用P

c#编程指南(十) 平台调用P

时间:2019-11-26 07:45:10

相关推荐

可以说新手使用P-INVOKE最开始的头疼就是C#和C++的字符串传递,因为这里涉及到两个问题。

第一:C#的string和C++的字符串首指针如何对应。

第二:字符串还有ANSI和UNICODE(宽字符串)之分。

本文分三部分阐述:

第一:字符串指针当输入参数,

第二:字符串指针作为返回值,

第三:字符串指针作为输入输出参数。

C++部分的测试代码很简单这里就全部贴出来了:

1 #include "stdafx.h"

2 #include "TestDll.h"

3 #include <stdio.h>

4 #include <string.h>

5 #include <tchar.h>

6

7

8 static char * _hello = "Hello,World!!";

9 static TCHAR * _helloW = TEXT("Hello,World!!");

10

11 void __stdcall PrintString(char * hello)

12 {

13 printf("%s\n",hello);

14 }

15

16 void __stdcall PrintStringW(TCHAR * hello)

17 {

18 _tprintf(TEXT("%s\n"),hello);

19 }

20

21

22 char * __stdcall GetStringReturn()

23 {

24 return _hello;

25 }

26

27 TCHAR * __stdcall GetStringReturnW()

28 {

29 return _helloW;

30 }

31

32

33 void __stdcall GetStringParam(char * outHello,int len)

34 { //output "aaaaaaaa"

35 for(int i= 0; i< len -1 ;i++) outHello[i] = "a";

36 outHello[len - 1] = "\0";

37 }

38

39 void __stdcall GetStringParamW(TCHAR * outHello,int len)

40 { //output "aaaaaaaa" unicode version.

41 for(int i= 0; i< len -1 ;i++) outHello[i] = TEXT("a");

42 outHello[len - 1] = TEXT("\0");

43 }

下面看C#如何调用。

第一:字符串指针作为输入参数,可以使用byte[] 和MarshalAs来解决。(注意四个P-INVOKE,两个ANSI版本,和两个UNICODE版本),推荐使用MarshalAs方法简单明了。

1 [DllImport("TestDll", EntryPoint = "PrintString")]

2 public static extern void PrintStringByBytes(byte[] hello);

3

4 [DllImport("TestDll", EntryPoint = "PrintString")]

5 public static extern void PrintStringByMarshal([MarshalAs(UnmanagedType.LPStr)]string hello);

6

7 [DllImport("TestDll", EntryPoint = "PrintStringW")]

8 public static extern void PrintStringByBytesW(byte[] hello);

9

10 [DllImport("TestDll", EntryPoint = "PrintStringW")]

11 public static extern void PrintStringByMarshalW([MarshalAs(UnmanagedType.LPWStr)]string hello);

12

13

14 public void Run()

15 {

16 PrintStringByBytes(Encoding.ASCII.GetBytes("use byte[]"));

17 PrintStringByMarshal("use MarshalAs");

18 PrintStringByBytesW(Encoding.Unicode.GetBytes("use byte[]"));

19 PrintStringByMarshalW("use MarshalAs");

20 }

第二:字符串指针作为返回值,和上面一样也有两种声明方法,同样也包含两个版本。注意:Marshal.PtrToStringAnsi()函数的使用,把字符串指针转变为C#的string.推荐使用MarshalAs方法简单明了。

1 [DllImport("TestDll", EntryPoint = "GetStringReturn")]

2 public static extern IntPtr GetStringReturnByBytes();

3

4 [DllImport("TestDll", EntryPoint = "GetStringReturn")]

5 [return:MarshalAs(UnmanagedType.LPStr)]

6 public static extern string GetStringReturnByMarshal();

7

8 [DllImport("TestDll", EntryPoint = "GetStringReturnW")]

9 public static extern IntPtr GetStringReturnByBytesW();

10

11 [DllImport("TestDll", EntryPoint = "GetStringReturnW")]

12 [return: MarshalAs(UnmanagedType.LPWStr)]

13 public static extern string GetStringReturnByMarshalW();

14

15

16 public void Run()

17 { //Marshal.PtrToStringAuto(GetStringReturnByBytes()); 自动判断类型不错。

18 Console.WriteLine(Marshal.PtrToStringAnsi(GetStringReturnByBytes()));

19 Console.WriteLine(GetStringReturnByMarshal());

20 Console.WriteLine(Marshal.PtrToStringUni(GetStringReturnByBytesW()));

21 Console.WriteLine(GetStringReturnByMarshalW());

22 }

第三:字符串指针作为输入输出参数时,因为要求有固定的容量,所以这里使用的是StringBuilder,大家仔细看了,当然也有byte[]版本。这个看大家喜欢那个版本就是用那个.

1 [DllImport("TestDll", EntryPoint = "GetStringParam")]

2 public static extern void GetStringParamByBytes(byte[] outHello, int len);

3

4 [DllImport("TestDll", EntryPoint = "GetStringParam")]

5 public static extern void GetStringParamByMarshal([Out, MarshalAs(UnmanagedType.LPStr)]StringBuilder outHello, int len);

6

7 [DllImport("TestDll", EntryPoint = "GetStringParamW")]

8 public static extern void GetStringParamByBytesW(byte[] outHello, int len);

9

10 [DllImport("TestDll", EntryPoint = "GetStringParamW")]

11 public static extern void GetStringParamByMarshalW([Out, MarshalAs(UnmanagedType.LPWStr)]StringBuilder outHello, int len);

12

13

14 public byte[] _outHello = new byte[10];

15 public byte[] _outHelloW = new byte[20];

16 public StringBuilder _builder = new StringBuilder(10); //很重要设定string的容量。

17

18 public void Run()

19 {

20 //

21 GetStringParamByBytes(_outHello, _outHello.Length);

22 GetStringParamByMarshal(_builder, _builder.Capacity);

23 GetStringParamByBytesW(_outHelloW, _outHelloW.Length / 2);

24 GetStringParamByMarshalW(_builder, _builder.Capacity);

25

26 //

27 Console.WriteLine(Encoding.ASCII.GetString(_outHello));

28 Console.WriteLine(_builder.ToString());

29 Console.WriteLine(Encoding.Unicode.GetString(_outHelloW));

30 Console.WriteLine(_builder.ToString());

31 }

32

下载:代码

如果觉得《c#编程指南(十) 平台调用P》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。