2

我有一个接受三个参数的 API

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

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

LPSTR的等价物是什么?

4

1 回答 1

6
[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”... 响应是:string或者StringBuilder如果您将字符串传递给方法,StringBuilder如果方法将字符串传递给您。另一种选择是使用 abyte[]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 字符串以 null 结尾。我们找到第一个\0withArray.IndexOf(buffer, (byte)0)并将字符转换为 null 为字符串 with 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。你可以通过一些参数来控制它。

于 2013-08-06T07:30:05.987 回答