Skip to content

Commit d91e11a

Browse files
authored
Look up the ICustomMarshaler implementation methods based on runtime type (#55439)
1 parent 67ecbe8 commit d91e11a

File tree

2 files changed

+66
-10
lines changed

2 files changed

+66
-10
lines changed

src/coreclr/vm/custommarshalerinfo.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,6 @@ CustomMarshalerInfo::CustomMarshalerInfo(LoaderAllocator *pLoaderAllocator, Type
6767
STRINGREF CookieStringObj = StringObject::NewString(strCookie, cCookieStrBytes);
6868
GCPROTECT_BEGIN(CookieStringObj);
6969
#endif
70-
71-
// Load the method desc's for all the methods in the ICustomMarshaler interface.
72-
m_pMarshalNativeToManagedMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalNativeToManaged, hndCustomMarshalerType);
73-
m_pMarshalManagedToNativeMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalManagedToNative, hndCustomMarshalerType);
74-
m_pCleanUpNativeDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpNativeData, hndCustomMarshalerType);
75-
m_pCleanUpManagedDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpManagedData, hndCustomMarshalerType);
76-
7770
// Load the method desc for the static method to retrieve the instance.
7871
MethodDesc *pGetCustomMarshalerMD = GetCustomMarshalerMD(CustomMarshalerMethods_GetInstance, hndCustomMarshalerType);
7972

@@ -103,15 +96,26 @@ CustomMarshalerInfo::CustomMarshalerInfo(LoaderAllocator *pLoaderAllocator, Type
10396
};
10497

10598
// Call the GetCustomMarshaler method to retrieve the custom marshaler to use.
106-
OBJECTREF CustomMarshalerObj = getCustomMarshaler.Call_RetOBJECTREF(GetCustomMarshalerArgs);
99+
OBJECTREF CustomMarshalerObj = NULL;
100+
GCPROTECT_BEGIN(CustomMarshalerObj);
101+
CustomMarshalerObj = getCustomMarshaler.Call_RetOBJECTREF(GetCustomMarshalerArgs);
107102
if (!CustomMarshalerObj)
108103
{
109104
DefineFullyQualifiedNameForClassW()
110105
COMPlusThrow(kApplicationException,
111106
IDS_EE_NOCUSTOMMARSHALER,
112107
GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable()));
113108
}
109+
// Load the method desc's for all the methods in the ICustomMarshaler interface based on the type of the marshaler object.
110+
TypeHandle customMarshalerObjType = CustomMarshalerObj->GetMethodTable();
111+
112+
m_pMarshalNativeToManagedMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalNativeToManaged, customMarshalerObjType);
113+
m_pMarshalManagedToNativeMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalManagedToNative, customMarshalerObjType);
114+
m_pCleanUpNativeDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpNativeData, customMarshalerObjType);
115+
m_pCleanUpManagedDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpManagedData, customMarshalerObjType);
116+
114117
m_hndCustomMarshaler = pLoaderAllocator->AllocateHandle(CustomMarshalerObj);
118+
GCPROTECT_END();
115119

116120
// Retrieve the size of the native data.
117121
if (m_bDataIsByValue)

src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler.cs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ public void Parameter_NotICustomMarshaler_ThrowsApplicationException()
365365
{
366366
Assert.Throws<ApplicationException>(() => NonICustomMarshalerMethod(""));
367367
}
368-
368+
369369
[DllImport(LibcLibrary, EntryPoint = "atoi", CallingConvention = CallingConvention.Cdecl)]
370370
public static extern int NonICustomMarshalerMethod([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(string))] string str);
371371

@@ -509,7 +509,7 @@ public void CleanUpNativeData(IntPtr pNativeData) { }
509509

510510
[Fact]
511511
public void Parameter_GetInstanceMethodThrows_ThrowsActualException()
512-
{
512+
{
513513
Assert.Throws<NotImplementedException>(() => ThrowingGetInstanceMethod(""));
514514
}
515515

@@ -588,6 +588,58 @@ public struct StructWithCustomMarshalerField
588588
[DllImport(LibcLibrary, EntryPoint = "atoi", CallingConvention = CallingConvention.Cdecl)]
589589
public static extern int StructWithCustomMarshalerFieldMethod(StructWithCustomMarshalerField c);
590590

591+
592+
[Fact]
593+
public void Parameter_DifferentCustomMarshalerType_MarshalsCorrectly()
594+
{
595+
Assert.Equal(234, DifferentCustomMarshalerType("5678"));
596+
}
597+
598+
public class OuterCustomMarshaler : ICustomMarshaler
599+
{
600+
public void CleanUpManagedData(object ManagedObj) => throw new NotImplementedException();
601+
public void CleanUpNativeData(IntPtr pNativeData) => throw new NotImplementedException();
602+
603+
public int GetNativeDataSize() => throw new NotImplementedException();
604+
605+
public IntPtr MarshalManagedToNative(object ManagedObj) => throw new NotImplementedException();
606+
public object MarshalNativeToManaged(IntPtr pNativeData) => throw new NotImplementedException();
607+
608+
public static ICustomMarshaler GetInstance(string cookie) => new InnerCustomMarshaler();
609+
610+
private interface ILargeInterface
611+
{
612+
void Method1();
613+
void Method2();
614+
void Method3();
615+
void Method4();
616+
void Method5();
617+
void Method6();
618+
}
619+
620+
private class InnerCustomMarshaler : ILargeInterface, ICustomMarshaler
621+
{
622+
public void Method1() => throw new InvalidOperationException();
623+
public void Method2() => throw new InvalidOperationException();
624+
public void Method3() => throw new InvalidOperationException();
625+
public void Method4() => throw new InvalidOperationException();
626+
public void Method5() => throw new InvalidOperationException();
627+
public void Method6() => throw new InvalidOperationException();
628+
629+
public void CleanUpManagedData(object ManagedObj) { }
630+
public void CleanUpNativeData(IntPtr pNativeData) => Marshal.FreeCoTaskMem(pNativeData);
631+
632+
public int GetNativeDataSize() => IntPtr.Size;
633+
634+
public IntPtr MarshalManagedToNative(object ManagedObj) => Marshal.StringToCoTaskMemAnsi("234");
635+
public object MarshalNativeToManaged(IntPtr pNativeData) => null;
636+
}
637+
}
638+
639+
[DllImport(LibcLibrary, EntryPoint = "atoi", CallingConvention = CallingConvention.Cdecl)]
640+
public static extern int DifferentCustomMarshalerType([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(OuterCustomMarshaler))] string str);
641+
642+
591643
public static int Main(String[] args)
592644
{
593645
return new ICustomMarshalerTests().RunTests();

0 commit comments

Comments
 (0)