• C# C++ 字符串传递


    C# C++ 字符串传递

    标签: c#c++bytestring测试c 

    2012-06-14 17:425707人阅读评论(3)收藏举报

    分类:

    C#(11)  作者同类文章X

     

    C++(112)  作者同类文章X

     

    可以说新手使用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 staticchar* _hello ="Hello,World!!";
     9 static TCHAR * _helloW = TEXT("Hello,World!!");
    10
    11 void __stdcall PrintString(char* hello)
    12{
    13 printf("%s ",hello);
    14}
    15
    16 void __stdcall PrintStringW(TCHAR * hello)
    17{
    18 _tprintf(TEXT("%s "),hello);
    19}
    20
    21
    22 char* __stdcall GetStringReturn()
    23{
    24return _hello;
    25}
    26
    27TCHAR * __stdcall GetStringReturnW()
    28{
    29return _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] ='';
    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('');
    43}

     

     

     

     

    下面看C#如何调用。

     

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

     

    1 [DllImport("TestDll", EntryPoint ="PrintString")]
     2publicstaticexternvoid PrintStringByBytes(byte[] hello);
     3
     4 [DllImport("TestDll", EntryPoint ="PrintString")]
     5publicstaticexternvoid PrintStringByMarshal([MarshalAs(UnmanagedType.LPStr)]string hello);
     6
     7 [DllImport("TestDll", EntryPoint ="PrintStringW")]
     8publicstaticexternvoid PrintStringByBytesW(byte[] hello);
     9
    10 [DllImport("TestDll", EntryPoint ="PrintStringW")]
    11publicstaticexternvoid PrintStringByMarshalW([MarshalAs(UnmanagedType.LPWStr)]string hello);
    12
    13
    14publicvoid 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")]
     2publicstaticextern IntPtr GetStringReturnByBytes();
     3
     4 [DllImport("TestDll", EntryPoint ="GetStringReturn")]
     5 [return:MarshalAs(UnmanagedType.LPStr)]
     6publicstaticexternstring GetStringReturnByMarshal();
     7
     8 [DllImport("TestDll", EntryPoint ="GetStringReturnW")]
     9publicstaticextern IntPtr GetStringReturnByBytesW();
    10
    11 [DllImport("TestDll", EntryPoint ="GetStringReturnW")]
    12 [return: MarshalAs(UnmanagedType.LPWStr)]
    13publicstaticexternstring GetStringReturnByMarshalW();
    14
    15
    16publicvoid 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")]
     2publicstaticexternvoid GetStringParamByBytes(byte[] outHello, int len);
     3
     4 [DllImport("TestDll", EntryPoint ="GetStringParam")]
     5publicstaticexternvoid GetStringParamByMarshal([Out, MarshalAs(UnmanagedType.LPStr)]StringBuilder outHello, int len);
     6
     7 [DllImport("TestDll", EntryPoint ="GetStringParamW")]
     8publicstaticexternvoid GetStringParamByBytesW(byte[] outHello, int len);
     9
    10 [DllImport("TestDll", EntryPoint ="GetStringParamW")]
    11publicstaticexternvoid GetStringParamByMarshalW([Out, MarshalAs(UnmanagedType.LPWStr)]StringBuilder outHello, int len);
    12
    13
    14publicbyte[] _outHello =newbyte[10];
    15publicbyte[] _outHelloW =newbyte[20];
    16public StringBuilder _builder =new StringBuilder(10); //很重要设定string的容量。
    17 
    18publicvoid 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}

  • 相关阅读:
    set命令_Linux
    AngularJS的date 过滤器
    JMeter环境介绍
    JMeter测试计划要素
    HTTP协议的压缩及URL Encode
    fiddler配置及使用教程
    Slenium常用方法
    Selenium八大定位
    CSS实现上下左右垂直居中
    SASS用法笔记
  • 原文地址:https://www.cnblogs.com/gosteps/p/5241850.html
Copyright © 2020-2023  润新知