diff --git a/src/tests/Interop/CMakeLists.txt b/src/tests/Interop/CMakeLists.txt index 1914910027eb47..35f34f87d6b49c 100644 --- a/src/tests/Interop/CMakeLists.txt +++ b/src/tests/Interop/CMakeLists.txt @@ -57,6 +57,7 @@ add_subdirectory(NativeLibrary/NativeLibraryToLoad) add_subdirectory(DllImportAttribute/DllImportPath) add_subdirectory(DllImportAttribute/ExactSpelling) add_subdirectory(ICustomMarshaler/ConflictingNames) +add_subdirectory(ICustomMarshaler/Primitives) add_subdirectory(LayoutClass) add_subdirectory(PInvoke/DateTime) if(CLR_CMAKE_TARGET_WIN32) diff --git a/src/tests/Interop/ICustomMarshaler/Primitives/CMakeLists.txt b/src/tests/Interop/ICustomMarshaler/Primitives/CMakeLists.txt new file mode 100644 index 00000000000000..1264ebcf0a2252 --- /dev/null +++ b/src/tests/Interop/ICustomMarshaler/Primitives/CMakeLists.txt @@ -0,0 +1,10 @@ +project (CustomMarshalersPrimitives) +include_directories(${INC_PLATFORM_DIR}) +set(SOURCES ICustomMarshalerNative.cpp ) + +# add the executable +add_library (CustomMarshalersPrimitives SHARED ${SOURCES}) +target_link_libraries(CustomMarshalersPrimitives ${LINK_LIBRARIES_ADDITIONAL}) + +# add the install targets +install (TARGETS CustomMarshalersPrimitives DESTINATION bin) diff --git a/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler.cs b/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler.cs index a8ef865e7a832b..9c383b70214aad 100644 --- a/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler.cs +++ b/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler.cs @@ -164,6 +164,37 @@ public static void Parameter_CustomMarshalerProvided_CallsMethodsInCorrectOrderi "Called CleanUpNativeData" }); Assert.Equal(expectedOrderingSecondCall, OrderTrackingCustomMarshaler.Events); + + // GetInstance is only called once. + string val3 = "7488"; + Assert.Equal(val3, OrderTrackingMethodRef(ref val3)); + IEnumerable expectedOrderingThirdCall = expectedOrderingSecondCall.Concat(new string[] + { + "Called MarshalManagedToNative", + "Called MarshalNativeToManaged", + "Called CleanUpManagedData", + "Called MarshalNativeToManaged", + "Called CleanUpNativeData", + }); + Assert.Equal(expectedOrderingThirdCall.Skip(7), OrderTrackingCustomMarshaler.Events.Skip(7)); + + OrderTrackingMethodOut(out var val4); + Assert.Equal("2334", val4); + IEnumerable expectedOrderingForthCall = expectedOrderingThirdCall.Concat(new string[] + { + "Called MarshalNativeToManaged", + }); + Assert.Equal(expectedOrderingForthCall.Skip(12), OrderTrackingCustomMarshaler.Events.Skip(12)); + + var val5 = OrderTrackingMethodDelegate(439, (x) => x.ToString()); + Assert.Equal("439", val5); + IEnumerable expectedOrderingFifthCall = expectedOrderingForthCall.Concat(new string[] + { + "Called MarshalManagedToNative", + "Called CleanUpManagedData", + "Called MarshalNativeToManaged", + }); + Assert.Equal(expectedOrderingFifthCall.Skip(13), OrderTrackingCustomMarshaler.Events.Skip(13)); } // This should only be used *once*, as it uses static state. @@ -201,7 +232,7 @@ public IntPtr MarshalManagedToNative(object ManagedObj) public object MarshalNativeToManaged(IntPtr pNativeData) { Events.Add("Called MarshalNativeToManaged"); - return pNativeData.ToInt32().ToString(); + return pNativeData.ToInt64().ToString(); } public static ICustomMarshaler GetInstance(string cookie) @@ -216,6 +247,20 @@ public static ICustomMarshaler GetInstance(string cookie) [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(OrderTrackingCustomMarshaler))] public static extern string OrderTrackingMethod([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(OrderTrackingCustomMarshaler))] string str); + [DllImport("CustomMarshalersPrimitives", EntryPoint = "NativeParseIntRef")] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(OrderTrackingCustomMarshaler))] + public static extern string OrderTrackingMethodRef([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(OrderTrackingCustomMarshaler))] ref string str); + + [DllImport("CustomMarshalersPrimitives", EntryPoint = "NativeParseIntOut")] + public static extern void OrderTrackingMethodOut([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(OrderTrackingCustomMarshaler))] out string str); + + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(OrderTrackingCustomMarshaler))] + public delegate string TestDelegate(int val); + + [DllImport("CustomMarshalersPrimitives", EntryPoint = "NativeParseIntDelegate")] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(OrderTrackingCustomMarshaler))] + public static extern string OrderTrackingMethodDelegate(int val, TestDelegate dlg); + public static void CustomMarshaler_BothMarshalTypeRefAndMarshalTypeProvided_PicksMarshalType() { Assert.Equal(2, BothTypeRefAndTypeMethod("64001")); @@ -613,6 +658,17 @@ public void CleanUpManagedData(object ManagedObj) { } [DllImport(LibcLibrary, EntryPoint = "atoi", CallingConvention = CallingConvention.Cdecl)] public static extern int DifferentCustomMarshalerType([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(OuterCustomMarshaler))] string str); + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BoxedValueTypeCustomMarshaler))] + public delegate string TestDelegateRef([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BoxedValueTypeCustomMarshaler))] ref int val); + + [DllImport("CustomMarshalersPrimitives", EntryPoint = "NativeParseIntDelegateRef")] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BoxedValueTypeCustomMarshaler))] + public static extern string CustomMarshallerWithDelegateRef(int val, TestDelegateRef dlg); + + public static void DelegateParameter_MarshalerOnRefInt_ThrowsMarshalDirectiveException() + { + Assert.Throws(() => CustomMarshallerWithDelegateRef(84664, (ref int x) => x.ToString())); + } public static int Main(String[] args) { try @@ -643,6 +699,7 @@ public static int Main(String[] args) Parameter_CleanUpNativeDataMethodThrows_ThrowsActualException(); Field_ParentIsStruct_ThrowsTypeLoadException(); Parameter_DifferentCustomMarshalerType_MarshalsCorrectly(); + DelegateParameter_MarshalerOnRefInt_ThrowsMarshalDirectiveException(); } catch (Exception e) { diff --git a/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshalerNative.cpp b/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshalerNative.cpp new file mode 100644 index 00000000000000..800cf1ad099869 --- /dev/null +++ b/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshalerNative.cpp @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include + +using TestDelegate = LPCSTR(STDMETHODCALLTYPE*)(int); +using TestDelegateRef = LPCSTR(STDMETHODCALLTYPE*)(int*); + +extern "C" int DLL_EXPORT STDMETHODCALLTYPE NativeParseInt(LPCSTR str) +{ + return atoi(str); +} + +extern "C" int DLL_EXPORT STDMETHODCALLTYPE NativeParseIntRef(LPCSTR* str) +{ + return atoi(*str); +} + +extern "C" void DLL_EXPORT STDMETHODCALLTYPE NativeParseIntOut(int* outVal) +{ + *outVal = 2334; +} + +extern "C" int DLL_EXPORT STDMETHODCALLTYPE NativeParseIntDelegate(int val, TestDelegate del) +{ + return atoi(del(val)); +} + +extern "C" int DLL_EXPORT STDMETHODCALLTYPE NativeParseIntDelegateRef(int val, TestDelegateRef del) +{ + return atoi(del(&val)); +} diff --git a/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler_TargetUnix.csproj b/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler_TargetUnix.csproj index 6fcc5f2e6ac204..d6ea6816acbb12 100644 --- a/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler_TargetUnix.csproj +++ b/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler_TargetUnix.csproj @@ -10,4 +10,7 @@ + + + diff --git a/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler_TargetWindows.csproj b/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler_TargetWindows.csproj index febed8fcc2aa01..44a0c80b382281 100644 --- a/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler_TargetWindows.csproj +++ b/src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler_TargetWindows.csproj @@ -11,4 +11,7 @@ + + +