C ++ LPSTR转C#字符串.Net包装器

mah*_*a22 2 .net c# string pinvoke

我有一个采用三个参数的API

BOOL GetServerName (int index, LPSTR Buffer, int BufSize); 
Run Code Online (Sandbox Code Playgroud)

我如何在C#中使用此方法

LPSTR的等效性是什么?

xan*_*tos 5

[DllImport("YourDll.dll", CharSet = CharSet.Ansi)]
//[return: MarshalAs(UnmanagedType.Bool)] // This line is optional, and it's implicit
static extern bool GetServerName(int index, StringBuilder buffer, int bufSize);
Run Code Online (Sandbox Code Playgroud)

要使用它:

int bufSize = 100;
StringBuilder buffer = new StringBuilder(bufSize);
bool result = GerServerName(0, buffer, bufSize);

if (result) 
{
    string buffer2 = buffer.ToString();
}
Run Code Online (Sandbox Code Playgroud)

从技术上讲,您的问题是“什么等效于LPSTR” ...响应是:string或者,StringBuilder如果您将字符串传递给方法,StringBuilder如果方法将字符串传递给您。另一种选择是使用a byte[]Encoding/Decoding自己动手,例如:

[DllImport("YourDll.dll", CharSet = CharSet.Ansi)]
//[return: MarshalAs(UnmanagedType.Bool)] // This line is optional, and it's implicit
static extern bool GetServerName(int index, byte[] buffer, int bufSize);
Run Code Online (Sandbox Code Playgroud)

int bufSize = 100;
byte[] buffer = new byte[bufSize];
bool result = GerServerName(0, buffer, bufSize);

if (result) 
{
    string buffer2 = Encoding.Default.GetString(buffer, 0, Array.IndexOf(buffer, (byte)0));
}
Run Code Online (Sandbox Code Playgroud)

(C字符串以null终止。我们找到第一个\0带有Array.IndexOf(buffer, (byte)0),并将最多null的字符转换为带有的字符串Encoding.Default.GetString())。

一些评论...

  1. 我希望您具有缓冲区的最大长度(如常量),因为通常这些方法被编写为以某种方式返回字符串的长度。
  2. 如果您有该方法的Unicode版本(可能是GetServerNameW),则应使用它。如果存在,最好使用Unicode方法,这样就不会丢失非Ansi字符。

附带说明,当您使用时DllImport,应检查您是否使用了正确的调用约定。对于Windows API,您不需要执行任何操作,但是根据头文件中方法的定义方式,您可能需要添加CallingConvention = CallingConvention.something)。通常(但现在总是如此),. NET运行时会因错误的调用约定而引发异常,否则该方法将不起作用,并会返回奇怪的内容或崩溃。这是因为调用约定告诉.NET必须如何将参数传递给方法(技术上,何处,如何以及谁必须释放堆栈)。头文件中的调用约定的一些示例是cdecl,stdcall,fastcall,thiscall,pascal(等同于stdcall),WINAPI,APIENTRY(等同于WINAPI),CALLBACK(等同于WINAPI)以及所有带有_或__或大写。Microsoft VC ++通常对C方法使用cdecl调用约定,对C ++方法使用thiscall。您可以通过一些参数来控制它。