C ++ LPSTR到C#String .Net Wrapper

时间:2013-08-06 07:13:00

标签: c# .net string pinvoke

我有一个带三个参数的API

BOOL GetServerName (int index, LPSTR Buffer, int BufSize); 

我如何在 C#

中使用此方法

LPSTR 的等价性是什么?

1 个答案:

答案 0 :(得分: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);

使用它:

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

if (result) 
{
    string buffer2 = buffer.ToString();
}

从技术上讲,你的问题是“什么等同于LPSTR”......如果您将字符串传递给方法,则响应为:stringStringBuilder,如果方法为StringBuilder将字符串传递给您。另一种方法是使用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);

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));
}

(C字符串以空值终止。我们找到第一个带有\0的{​​{1}},我们将字符转换为null为Array.IndexOf(buffer, (byte)0)的字符串。

一些评论......

  1. 我希望你有最大的缓冲区长度(比如常量),因为通常这些方法都是以某种方式返回字符串的长度。
  2. 如果你有该方法的Unicode版本(也许是Encoding.Default.GetString()),你应该使用它。如果存在,最好使用Unicode方法,因此不会丢失非Ansi字符。
  3. 作为旁注,当您使用GetServerNameW时,您应该检查您是否使用了正确的调用约定。对于Windows API,您不需要执行任何操作,但根据头文件中方法的定义方式,您可能需要添加DllImport)。通常(但现在总是).NET运行时将在错误的调用约定上抛出异常,或者该方法将无法工作并返回奇怪的东西或将崩溃。这是因为调用约定告诉.NET必须如何将参数传递给方法(技术上在哪里,如何以及谁必须释放堆栈)。头文件中调用约定的一些示例是cdecl,stdcall,fastcall,thiscall,pascal(相当于stdcall),WINAPI,APIENTRY(相当于WINAPI),CALLBACK(相当于WINAPI)以及带有_或__前置的所有这些单词或在所有大写字母中。 Microsoft VC ++通常使用C方法的cdecl调用约定和C ++方法的thiscall。您可以通过某些arguments来控制它。