2009-11-01 105 views

回答

12

您可以通過StringBuilder作爲char*

查看http://pinvoke.net以查看函數的簽名是否已經存在。

+2

+1,或者只是'string',如果它只是一個輸入參數。 – user7116 2009-11-01 21:50:46

+3

我授予這個答案,因爲你基本上回答了我的問題,但似乎至少爲我所做的一切需要的是固定的(char * s = string){...} – Kris 2009-11-02 10:08:05

+17

我試着用SecureString(char *,int length)以及SecureString(sb,sb.Length)或SecureString((char *)sb,sb.Length)都不起作用。說不能將System.Text.StringBuilder轉換爲char *。 – Despertar 2012-06-08 02:24:53

0

你可以得到的byte []使用字符串數組Encoding.ASCII.GetBytes。 這可能轉換爲char *在C#中使用固定語句。 (這引腳分配的內存,不允許gc移動它 - 然後你可以做一個指針)。

所以我的回答是,只有當你設法將byte *轉換爲char *。 (在C/C++中這不會是一個問題,但我不確定C#)

PS>如果我在此找到一篇文章的書籤,我會稍後發佈一些代碼。我知道我有它..

+0

你也應該考慮Encoding.UTF8因爲這將保存所有Unicode字符。 – asveikau 2009-11-01 21:14:28

+0

或者,如果傳遞給本機Win32函數,最好使用Encoding.Unicode(和C端的PWSTR)... – asveikau 2009-11-01 21:16:14

+0

如果這些不是多字節,你必須首先檢查(我認爲它們實際上是),因爲這使得它「複雜一點」。 – kubal5003 2009-11-01 21:35:51

4

這取決於你想要做什麼。當您通過PInvoke調用Win32函數時,您應該只能傳遞字符串變量;該框架爲您整理所有內容。如果您需要更復雜的東西,請參閱Marshal.StringToHGlobalAnsiMarshal類的其他方法。

4

要結合已經給出的2個肛門,它取決於你的參數需要的方向。

如果函數只需要輸入字符串,即const char *,則可以使用類型爲System.String(或普通的string)的參數。

如果函數填充字符串,即char * buffer, int bufferSize,則可以傳遞System.Text.StringBuilder

在這兩種情況下,(自動)封送會爲您做必要的轉換。

+0

感謝您的見解,但我在下面的帖子的評論中還有一些評論... – Kris 2009-11-02 01:06:28

+1

感謝您解釋只需一個字符串的函數和構建字符串的函數之間的區別。每個人都只是不斷推薦'StringBuilder',但如果函數不會修改字符串,那看起來不太合適。 – mpen 2013-07-08 06:32:08

35

那麼你當然可以這樣做:

string str = "my string"; 

unsafe 
{ 
    fixed (char* p = str) 
    {    
     // do some work 
    } 
} 

那裏有一個運營商(的char *)綁定到字符串對象。 但是,輸出格式可能與底層C或其他格式不兼容......然而,這是解析字符串的很好的解決方案。 希望對閱讀本文的讀者有所幫助。

+0

這給出了一個指向'System.Char'元素的指針,它對應於Win32的'WCHAR *',但問題是要求'char *'。 – 2018-03-09 20:59:34

4

沒有不安全的上下文是必需的下面的代碼段(和是它顯示有關string執行內部螺栓和比特的GetHashCode方法示出了它與一個在Java中的差異,因爲在C#哈希碼ISN'的值牛逼緩存,通常它表明,C#字符串不是一成不變的,最終你可能被教導一樣,不能與豐尼曼處理):

using System; 
using System.Runtime.InteropServices; 

namespace Guess 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      const string str = "ABC"; 

      Console.WriteLine(str); 
      Console.WriteLine(str.GetHashCode()); 

      var handle = GCHandle.Alloc(str, GCHandleType.Pinned); 

      try 
      { 
       Marshal.WriteInt16(handle.AddrOfPinnedObject(), 4, 'Z'); 

       Console.WriteLine(str); 
       Console.WriteLine(str.GetHashCode()); 
      } 
      finally 
      { 
       handle.Free(); 
      } 
     } 
    } 
} 
+0

這是不正確的,請參閱http://stackoverflow.com/a/10980174/3427520 – zwcloud 2017-04-06 04:54:12

+2

@zwcloud **它完全錯誤的事情陳述,答案是正確的,最有效的和最不固定的上下文(與不安全的上下文)* *。答案完全是要求做的。通過'GCHandle.alloc'鎖定字符串的指針不會造成任何內存泄漏,除非您稍後在基礎上下文中強制使用指針。 C#中的整個指針/內存概念被認爲是低級/高級主題,如果你使用指針,這意味着你理解整個概念並基本知道你在做什麼。 – Lu4 2017-04-10 22:04:28

+2

關於引用的問題和答案,這個問題是完全有效的,但與上述問題無關,沒有提到任何人都會存儲指針。如果你以後用C#創建的字符串,顯然你需要將它複製到C中,因爲它會涉及C中的那個字符串的分配,這將允許C稍後釋放它。所以它通常意味着你不能將你的指針固定在生活中,既不是在C#中編制(創建)你的字符串的副本並將它存儲在C中也是好的,因爲C將不能在稍後解除分配它。 – Lu4 2017-04-10 22:11:46