Vegard Larsen
Vegard Larsen

Reputation: 13037

Passing string from .NET to native (64-bit)

I am having an issue passing a simple string from my .NET app, compiled as 64-bit, to my native DLL, also compiled as 64-bit.

C++ signature:

DllExport void SetFoo(LPWSTR foo);

C# signature:

[DllImport(Library, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
internal static extern void SetFoo(
     [In][MarshalAs(UnmanagedType.LPWStr)] string foo);

Then I run the following code in C#:

X.SetFoo("some string");

When it reaches the debugger in the DLL, the value is swearing at me in Chinese: Ⴐ虘翺

When I change both the .NET and native code to 32-bit, the value I get in the debugger is the correct string. Where am I being stupid?

Minimal reproduction as a Visual Studio 2015 Solution: download here

To reproduce:

Foo.h:

extern "C" {
    __declspec( dllexport ) void SetFoo(LPWSTR);
}

Foo.cpp:

#include "stdafx.h"
#include "Foo.h"

DllExport void SetFoo(LPWSTR foo) 
{

}

Form1.cs:

[DllImport("Win32Project1.dll", CallingConvention = CallingConvention.Cdecl,  CharSet = CharSet.Unicode)]
public static extern void SetFoo(string text);

Upvotes: 1

Views: 658

Answers (1)

David Heffernan
David Heffernan

Reputation: 612964

When you interpret ANSI encoded latin text as UTF-16 you see Chinese characters. That's clearly what is happening. So your C# code is sending ANSI encoded text somehow.

The p/invoke would be better written like this:

[DllImport(Library, CallingConvention = CallingConvention.Cdecl, 
    CharSet = CharSet.Unicode)]
internal static extern void SetFoo(string foo);

The [in] is not needed, it is the default. And the MarshalAs is pointless since you specified CharSet.Unicode. However, neither change affects the semantics.

The only sound explanations for what you describe in the question are:

  • The actual code is not as you have described it, or
  • There is a defect in the debugger.

I suggest that you change the unmanaged function to

DllExport void SetFoo(LPWSTR foo) 
{
    MessageBoxW(0, L"", foo, MB_OK);
}

If the message box displays the correct text then the conclusion would appear to be that the debugger is defective.

Upvotes: 1

Related Questions