2009-11-01 158 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