0
extern "C"
__declspec(dllexport)
bool FillString(LPWSTR OutName)
{
    LPWSTR out = L"TheName\0";
    int len = wcslen(out);
    memcpy(
                OutName,
                out,
                len * sizeof(wchar_t));
    return true;
}

That is function in my c/c++ dll, the following is my call from c#...

[DllImport(@"My.dll", EntryPoint = "FillString", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool MyFunction([MarshalAsAttribute(UnmanagedType.LPWStr)] StringBuilder Name);

var fromdll = new StringBuilder(64); 
// I do not know length of out string (Name), but it is null terminated

bool IsFilled = MyFunction(fromdll);

Console.WriteLine(fromdll);

The output is

TheName???

Can anyone help me to get the output...?

TheName

TEDSON
  • 191
  • 2
  • 13
  • 1
    Is there a reason you don't use e.g. [`wcscpy`](http://en.cppreference.com/w/cpp/string/wide/wcscpy)? – Some programmer dude Aug 22 '16 at 14:16
  • StringBuilder is mutable, but here is cast to C string, then nothing positive happens. – Jacek Cz Aug 22 '16 at 14:22
  • Seems like you are copying wcslen characters, without \0. Try to copy `(len+1) * sizeof(wchar_t)` characters. – Paweł Dyl Aug 22 '16 at 14:25
  • No reason I never used wcscpy, I just never heard of it, I will look into it for better than memcpy. Anyway, your suggestion solved my issue, and I am grateful for such a swift response. Thank you. – TEDSON Aug 22 '16 at 14:36
  • The function is not only wrong but also very dangerous. It requires an extra *bufferSize* argument so it cannot corrupt memory. Copy the string with `wcscpy_s()`. Pass fromdll.Capacity. – Hans Passant Aug 22 '16 at 14:56
  • For the record, the string filling the buffer will never even come close to 64 chars, I wrote the code just as a simple example so as not to obscure my actual problem. I will examine more secure function for the copy. Thank you all for your feedback. – TEDSON Aug 22 '16 at 19:10

1 Answers1

0

You need to copy one more character. '\0' is called string terminator. Without it C, C++ and PInvoke in .NET do not recognize end of string. If you are copying wcslen characters, zero is not copied. There are many solutions:

  1. Use mentioned wcscpy to copy string with \0
  2. Copy one more character with memcpy(OutName, out, (len + 1) * sizeof(wchar_t)).

Moreover, it's a good idea to pass buffer (StringBuilder) size. C/C++ lets you write outside variable boudaries. This size enables to avoid that.

Paweł Dyl
  • 8,888
  • 1
  • 11
  • 27
  • I never realized there were multiple comments above, this answer solved my direct issue. Thanks. – TEDSON Aug 22 '16 at 14:49