Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,17 @@ internal static unsafe void ConvertToNative(string? strManaged, IntPtr nativeHom
managed.Slice(0, numChars).CopyTo(native);
native[numChars] = '\0';
}

internal static unsafe string ConvertToManaged(IntPtr nativeHome, int length)
{
int end = SpanHelpers.IndexOf(ref *(char*)nativeHome, '\0', length);
if (end != -1)
{
length = end;
}

return new string((char*)nativeHome, 0, length);
}
} // class WSTRBufferMarshaler
#if FEATURE_COMINTEROP

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/corelib.h
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,7 @@ DEFINE_METHOD(CSTRMARSHALER, CLEAR_NATIVE, ClearNative,

DEFINE_CLASS(FIXEDWSTRMARSHALER, StubHelpers, FixedWSTRMarshaler)
DEFINE_METHOD(FIXEDWSTRMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, SM_Str_IntPtr_Int_RetVoid)
DEFINE_METHOD(FIXEDWSTRMARSHALER, CONVERT_TO_MANAGED, ConvertToManaged, SM_IntPtr_Int_RetStr)

DEFINE_CLASS(BSTRMARSHALER, StubHelpers, BSTRMarshaler)
DEFINE_METHOD(BSTRMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, SM_Str_IntPtr_RetIntPtr)
Expand Down
7 changes: 2 additions & 5 deletions src/coreclr/vm/ilmarshalers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1906,11 +1906,8 @@ void ILFixedWSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmi
STANDARD_VM_CONTRACT;

EmitLoadNativeHomeAddr(pslILEmit);
pslILEmit->EmitDUP();
pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);

pslILEmit->EmitNEWOBJ(METHOD__STRING__CTOR_CHARPTR, 1);
pslILEmit->EmitLDC(m_pargs->fs.fixedStringLength);
pslILEmit->EmitCALL(METHOD__FIXEDWSTRMARSHALER__CONVERT_TO_MANAGED, 2, 1);
EmitStoreManagedValue(pslILEmit);
}

Expand Down
18 changes: 17 additions & 1 deletion src/tests/Interop/StringMarshalling/LPTSTR/LPTSTRTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
class LPTStrTest
{
private static readonly string InitialString = "Hello World";
private static readonly string LongString = "0123456789abcdefghi";
private static readonly string LongUnicodeString = "👨‍👨‍👧‍👧🐱‍👤";

public static int Main()
{
Expand Down Expand Up @@ -58,7 +60,21 @@ private static void RunByValTStrTests()
};

ReverseByValStringUni(ref uniStr);

Assert.AreEqual(Helpers.Reverse(InitialString), uniStr.str);

ReverseCopyByValStringAnsi(new ByValStringInStructAnsi { str = LongString }, out ByValStringInStructSplitAnsi ansiStrSplit);

Assert.AreEqual(Helpers.Reverse(LongString[^10..]), ansiStrSplit.str1);
Assert.AreEqual(Helpers.Reverse(LongString[..^10]), ansiStrSplit.str2);

ReverseCopyByValStringUni(new ByValStringInStructUnicode { str = LongString }, out ByValStringInStructSplitUnicode uniStrSplit);

Assert.AreEqual(Helpers.Reverse(LongString[^10..]), uniStrSplit.str1);
Assert.AreEqual(Helpers.Reverse(LongString[..^10]), uniStrSplit.str2);

ReverseCopyByValStringUni(new ByValStringInStructUnicode { str = LongUnicodeString }, out ByValStringInStructSplitUnicode uniStrSplit2);

Assert.AreEqual(Helpers.Reverse(LongUnicodeString[^10..]), uniStrSplit2.str1);
Assert.AreEqual(Helpers.Reverse(LongUnicodeString[..^10]), uniStrSplit2.str2);
}
}
12 changes: 12 additions & 0 deletions src/tests/Interop/StringMarshalling/LPTSTR/LPTStrTestNative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,15 @@ extern "C" DLL_EXPORT void STDMETHODCALLTYPE ReverseByValStringUni(ByValStringIn
{
StringMarshalingTests<LPWSTR, TP_slen>::ReverseInplace(str->str);
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE ReverseCopyByValStringAnsi(ByValStringInStructAnsi str, ByValStringInStructAnsi* out)
{
*out = str;
StringMarshalingTests<char*, default_callconv_strlen>::ReverseInplace(out->str);
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE ReverseCopyByValStringUni(ByValStringInStructUnicode str, ByValStringInStructUnicode* out)
{
*out = str;
StringMarshalingTests<LPWSTR, TP_slen>::ReverseInplace(out->str);
}
23 changes: 23 additions & 0 deletions src/tests/Interop/StringMarshalling/LPTSTR/LPTStrTestNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,31 @@ public struct ByValStringInStructAnsi
public string str;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ByValStringInStructSplitAnsi
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string str1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string str2;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct ByValStringInStructUnicode
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string str;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct ByValStringInStructSplitUnicode
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string str1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string str2;
}

[DllImport(nameof(LPTStrTestNative), CharSet = CharSet.Unicode)]
public static extern bool Verify_NullTerminators_PastEnd(StringBuilder builder, int length);

Expand All @@ -36,4 +54,9 @@ public struct ByValStringInStructUnicode
public static extern void ReverseByValStringAnsi(ref ByValStringInStructAnsi str);
[DllImport(nameof(LPTStrTestNative))]
public static extern void ReverseByValStringUni(ref ByValStringInStructUnicode str);

[DllImport(nameof(LPTStrTestNative))]
public static extern void ReverseCopyByValStringAnsi(ByValStringInStructAnsi str, out ByValStringInStructSplitAnsi strOut);
[DllImport(nameof(LPTStrTestNative))]
public static extern void ReverseCopyByValStringUni(ByValStringInStructUnicode str, out ByValStringInStructSplitUnicode strOut);
}