程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C#調用C++DLL時的編碼轉換

C#調用C++DLL時的編碼轉換

編輯:關於C語言
 最近項目,需要在C++(C++培訓 )#(C#培訓 中調用C++ 寫的DLL,因為C# 默認的編碼方式是Unicode,而調用的DLL規定只處理UTF8編碼格式的字符串,DLL中的輸入參數類型char*被我Marshal成 byte[],輸出參數類型char**被我Marshal成了string(C++和C#之間的類型轉換請參閱相關資料),於是我就經歷了無數次用於接收時的string-->string(UTF8-->Unicode)和用於發送時的string-->byte[] (Unicode-->UTF8)這樣頻繁的編碼轉換,期間多次出現中文亂碼,看來編碼轉換並非想象中那麼簡單,今天花時間google一番,原來以前的理解確實不夠深,存在很多誤區,現整理如下:

  (一)、Encoding和CharSet

  為什麼先提這兩個,實屬問題之源。在C#中包裝DLL的時候,DllImportAttribute當中的選項CharSet著實讓我糊塗了很久,MSDN曰:規定封送字符串應使用何種字符集,其中枚舉值有Ansi和Unicode,我真不知道到底改選哪一個。於是乎, google一番,Encoding這棵救命草被我找到,同時也釋疑了不少疑惑。

  首先,字符集不同於編碼,以前總將它們混為一談,CharSet是字符集,Encoding是編碼。字符集是字符的集合,規定這個集合裡有哪些字符,每個字符都有一個整數編號(只是編號不是編碼);而編碼是用來規定字符編號如何與二進制交互,每個“字符”分別用一個字節還是多個字節存儲。啊嗚,原來這樣,那我這裡接觸到的Ansi、Unicode、UTF8等等等等究竟是怎麼回事呢,借此機會,一探究竟!^_^

  (二)、Ansi、Unicode、UTF8、bala bala

  提到字符集,有ASCII、GB2312、GBK、GB18030、BIG5、JIS等等多種,與此相對應的編碼方式為ASCII、 GB2312、GBK、GB18030、BIG5、JIS(囧,難怪糊塗如我般的人如此多),但是Unicode字符集卻有多種編碼方式:UTF-8、 UTF-7、UTF-16、 UnicodeLittle、UnicodeBig。原來如此,字符集與編碼原來是這個樣子。ˇˍˇ|||

  那Ansi又是什麼呢?

  Ansi:系統編碼的發展經歷了三個階段,ASCIIàAnsi(不同國家語言本地化)àUnicode(標准化),原來Ansi編碼也好,Ansi字符集也好,都是指本地化的東西,在簡體中文系統下,ANSI 編碼代表 GB2312 編碼,Windows下自帶的記事本程序,默認的就是ANSI編碼。呵呵,那偶就去試試吧,輸入“anhui合肥”(不含引號),保存編碼方式選 “ANSI”,查看,哦,9個字節,明白了,原來Ansi編碼保留了對ASCII編碼的兼容,當遇到ASCII字符時,采用單字節存儲,當遇到非 ASCII編碼時,采用雙字節表示(GB2312編碼)。

  (三)、DllImportAttribute中的CharSet枚舉值選擇

  對字符集和編碼的概念清楚了以後,終於可以研究C#中調用非托管的DLL的方法咯。從托管應用程序去調用非托管代碼,如果 CharSet=Unicode,則DLL中的接口函數將出現的所有字符串(包括參數和返回值)視為Unicode字符集,Ansi一樣的道理。真不錯,了解到這裡總算有點撥雲見日的感覺了!O(∩_∩)O

  好像目前需要了解的知識點都差不多了,終於可以開始來解決我的問題了, (*^__^*)。回顧整理一下,第一:我需要調用非托管代碼,第二:非托管代碼只處理UTF8編碼格式的字符,第三,萬惡的中文亂碼,接口函數簽名中,無論參數還是返回值,接收到或是發送出的字符串都含有中文。呵呵,看來上面的知識應該可以解決這個問題了:首先接收字符串,因為接收到的是UTF8編碼格式,CharSet屬性肯定要設置成Unicode了,接收後要正確顯示中文,在當前系統中,需要將編碼方式轉換成GB2312,即 Encoding.Default;另外關於發送字符數組,因為無論是C#中默認的Unicode編碼方式,還是DLL處理時規定的UTF8編碼方式,都是Unicode字符集的一種編碼方式,所以CharSet也要設置成Unicode,只是要在發送前需要將字符數組轉換一下編碼方式。以下附帶兩個簡單的函數實現。

  以下是代碼片段:

  // 轉換接收到的字符串

  public string UTF8ToUnicode(string recvStr)

  {

  byte[] tempStr = Encoding.UTF8.GetBytes(recvNotify);

  byte[] tempDef = Encoding.Convert(Encoding.UTF8, Encoding.Default, tempStr);

  string msgBody = Encoding.Default.GetString(tempDef);

  return msgBody;

  }

  // 轉換要發送的字符數組

  public byte[] UnicodeToUTF8(string sendStr)

  {

  string tempStr = Encoding.UTF8.GetString(sendStr);

  byte[] msgBody = Encoding.UTF8.GetBytes(tempUTF8);

  return msgBody;

  }

  總結一下,本文因項目完成的需要,難免存在局限性,只討論了兩種情況:Unicode編碼的字符串轉UTF8格式的字符數組,以及UTF8格式的字符串轉Unicode格式的字符串,上面兩個方法均通過測試,至此總算解決了中文亂碼的問題。平台調用的知識點很多,只有真正掌握必需的基礎知識和平台調用的原理,才能做到活學活用。


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved