6

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

HANDLE  Connect(LPCSTR MachineName, LPCSTR ServerName, BOOL EnableDLLBuffering); 

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

的等价物是LPCSTR什么?应该用什么代替HANDLE

4

3 回答 3

11

HANDLE等效的是(IntPtr或者您可以使用 的子类之一SafeHandle,其中许多子类在命名空间中定义Microsoft.Win32.SafeHandles)。等效于LPCSTRis stringor StringBuilder(但string更好,因为您将字符串传递给方法并且方法不会修改它)。您甚至可以使用 a byte[](正如我在另一个响应中写给您的,但您必须在缓冲区中对字符串进行编码,并\0在末尾添加 a ......这很不方便)。最后 an是该方法不会修改LPCSTR的常量。LPSTR最好CharSet.Ansi在其他响应中设置为。

[DllImport("YourDll.dll", CharSet = CharSet.Ansi)]
static extern IntPtr Connect(string machineName, string serverName, bool enableDLLBuffering);

你称之为:

IntPtr ptr = Connect("MyMachine", "MyServer", true);

或者,如果您真的想自己进行编码:

[DllImport("YourDll.dll", CharSet = CharSet.Ansi)]
static extern IntPtr Connect(byte[] machineName, byte[] serverName, bool enableDLLBuffering);

public static byte[] GetBytesFromStringWithZero(Encoding encoding, string str)
{        
    int len = encoding.GetByteCount(str);

    // Here we leave a "space" for the ending \0
    // Note the trick to discover the length of the \0 in the encoding:
    // It could be 1 (for Ansi, Utf8, ...), 2 (for Unicode, UnicodeBE), 4 (for UTF32)
    // We simply ask the encoder how long it would be to encode it :-)
    byte[] bytes = new byte[len + encoding.GetByteCount("\0")];
    encoding.GetBytes(str, 0, str.Length, bytes, 0);
    return bytes;
}

IntPtr ptr = Connect(
                 GetBytesFromStringWithZero(Encoding.Default, "MyMachine"),
                 GetBytesFromStringWithZero(Encoding.Default, "MyServer"), 
                 true);

如果您必须始终使用相同的字符串多次调用该方法,则此变体会更好,因为您可以缓存字符串的编码版本并提高速度(是的,通常这是无用的优化)

于 2013-08-06T08:05:45.973 回答
7

根据How to map Win32 types to C# types when using P/Invoke?

  • LPCSTR (C) - 字符串 (C#)
  • 句柄 (C) - IntPtr (C#)
于 2013-08-06T08:07:52.023 回答
1

我使用 StringBuilder:

    [DllImport("user32.dll", CharSet = CharSet.Ansi)]
    static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

    var sb = new StringBuilder();
    var ret = GetClassName(hwnd, sb, 100);
    var klass = sb.ToString();
于 2018-08-24T06:48:24.917 回答