I have an API that takes three parameters:
HANDLE Connect(LPCSTR MachineName, LPCSTR ServerName, BOOL EnableDLLBuffering);
How can I use this method in C#?
What is the equivalence of LPCSTR
? And what should be use in place of HANDLE
?
The HANDLE
equivalent is IntPtr
(or you could use one of the subclasses of SafeHandle
, many of which are defined in the namespace Microsoft.Win32.SafeHandles
). The equivalent of LPCSTR
is string
or StringBuilder
(but string
is better, because you are passing the string to the method and the method won't modify it). You can even use a byte[]
(as I have wrote you in the other response, but you must encode your string in the buffer, and add a \0
at the end... it's quite inconvenient). In the end an LPCSTR
is a constant LPSTR
that the method won't modify. It's better you set the CharSet.Ansi
as in the other response.
[DllImport("YourDll.dll", CharSet = CharSet.Ansi)]
static extern IntPtr Connect(string machineName, string serverName, bool enableDLLBuffering);
and you call it as:
IntPtr ptr = Connect("MyMachine", "MyServer", true);
or, if you really want to do the encoding yourself:
[DllImport("YourDll.dll", CharSet = CharSet.Ansi)]
static extern IntPtr Connect(byte[] machineName, byte[] serverName, bool enableDLLBuffering);
and
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);
This variant is better if you have to call the method many many times always with the same strings, because you can cache the encoded versions of the string and gain something in speed (yes, normally it's an useless optimization)
HANDLE
is an opaque type. You pass it around other methods that use it. The library should have some methods that accept an HANDLE
, and it should have a CloseHandle
method to close it in the end (otherwise you cause a leak)
According to How to map Win32 types to C# types when using P/Invoke?:
LPCTSTR
, not LPCSTR
. I have no idea if they're equivalent or not, just wanted to mention it.
Commented
Aug 6, 2013 at 8:20
I use 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();
SafeHandle
, and it doesn't speak of encoding a string manually.