It is my understanding (and please correct me if I'm wrong) that the only difference between them is whether the string might be modified by the called function. (PCWSTR , LPWSTR)
I am now trying to pass a string from C# to a function expecting a PCWSTR, but all I can find is [MarshalAs(UnmanagedType.LPWStr)]. Am I correct that that is fine? (Yes, it works. That, though, is not a proof that it's fine. Some things work but then cause memory leaks etc.)
PCWSTR is a time anachronism, dinosaur-and-humans movie style. Finding a 16-bit program that uses short pointers on a Unicode string is like finding a white elephant. Only the distinct between LPCWSTR and LPWSTR is meaningful.
The C in LPCWSTR is simply annotation for const, a C language keyword. It promises that the called function never modifies the string that you pass. Which is very important to know in that language, it is not safe to pass a string literal to a LPWSTR argument. That is very likely to crash the program when it tries to update the string and fails because the memory page is read-only.
And it matters when you pinvoke. Passing a System.String to a LPCWSTR argument is fine, strings are immutable in .NET so you'll get a guarantee that an interned string literal isn't going to get mangled. A very hard to diagnose problem. Using [MarshalAs(UnmanagedType.LPWStr)] explicitly should not be necessary in general, you'd use the CharSet.Auto property in the [DllImport] attribute and get the LPWStr marshaling for free.
But if the argument type is LPWSTR then you must pass a StringBuilder instead. With a sufficient Capacity to allow the native code to poke around in the builder buffer to write the string.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With