我有一个接受三个参数的 API
BOOL GetServerName (int index, LPSTR Buffer, int BufSize);
如何在 C# 中使用此方法
LPSTR 的等价物是什么?
最佳答案
[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
如果方法将字符串传递给您。另一种选择是使用 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
和 Array.IndexOf(buffer, (byte)0)
并将字符转换为使用 Encoding.Default.GetString()
) 将 null 转换为字符串。
一些评论...
- 我希望你有缓冲区的最大长度(就像一个常量),因为通常这些方法被写成以某种方式返回字符串的长度。
- 如果您有该方法的 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。你可以通过一些arguments来控制它.
关于c# - C++ LPSTR 到 C# 字符串 .Net Wrapper,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18073857/