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
20 changes: 12 additions & 8 deletions src/coreclr/vm/custommarshalerinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,6 @@ CustomMarshalerInfo::CustomMarshalerInfo(LoaderAllocator *pLoaderAllocator, Type
STRINGREF CookieStringObj = StringObject::NewString(strCookie, cCookieStrBytes);
GCPROTECT_BEGIN(CookieStringObj);
#endif

// Load the method desc's for all the methods in the ICustomMarshaler interface.
m_pMarshalNativeToManagedMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalNativeToManaged, hndCustomMarshalerType);
m_pMarshalManagedToNativeMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalManagedToNative, hndCustomMarshalerType);
m_pCleanUpNativeDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpNativeData, hndCustomMarshalerType);
m_pCleanUpManagedDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpManagedData, hndCustomMarshalerType);

// Load the method desc for the static method to retrieve the instance.
MethodDesc *pGetCustomMarshalerMD = GetCustomMarshalerMD(CustomMarshalerMethods_GetInstance, hndCustomMarshalerType);

Expand Down Expand Up @@ -103,15 +96,26 @@ CustomMarshalerInfo::CustomMarshalerInfo(LoaderAllocator *pLoaderAllocator, Type
};

// Call the GetCustomMarshaler method to retrieve the custom marshaler to use.
OBJECTREF CustomMarshalerObj = getCustomMarshaler.Call_RetOBJECTREF(GetCustomMarshalerArgs);
OBJECTREF CustomMarshalerObj = NULL;
GCPROTECT_BEGIN(CustomMarshalerObj);
CustomMarshalerObj = getCustomMarshaler.Call_RetOBJECTREF(GetCustomMarshalerArgs);
if (!CustomMarshalerObj)
{
DefineFullyQualifiedNameForClassW()
COMPlusThrow(kApplicationException,
IDS_EE_NOCUSTOMMARSHALER,
GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable()));
}
// Load the method desc's for all the methods in the ICustomMarshaler interface based on the type of the marshaler object.
TypeHandle customMarshalerObjType = CustomMarshalerObj->GetMethodTable();

m_pMarshalNativeToManagedMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalNativeToManaged, customMarshalerObjType);
m_pMarshalManagedToNativeMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalManagedToNative, customMarshalerObjType);
m_pCleanUpNativeDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpNativeData, customMarshalerObjType);
m_pCleanUpManagedDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpManagedData, customMarshalerObjType);

m_hndCustomMarshaler = pLoaderAllocator->AllocateHandle(CustomMarshalerObj);
GCPROTECT_END();

// Retrieve the size of the native data.
if (m_bDataIsByValue)
Expand Down
56 changes: 54 additions & 2 deletions src/tests/Interop/ICustomMarshaler/Primitives/ICustomMarshaler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ public void Parameter_NotICustomMarshaler_ThrowsApplicationException()
{
Assert.Throws<ApplicationException>(() => NonICustomMarshalerMethod(""));
}

[DllImport(LibcLibrary, EntryPoint = "atoi", CallingConvention = CallingConvention.Cdecl)]
public static extern int NonICustomMarshalerMethod([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(string))] string str);

Expand Down Expand Up @@ -509,7 +509,7 @@ public void CleanUpNativeData(IntPtr pNativeData) { }

[Fact]
public void Parameter_GetInstanceMethodThrows_ThrowsActualException()
{
{
Assert.Throws<NotImplementedException>(() => ThrowingGetInstanceMethod(""));
}

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


[Fact]
public void Parameter_DifferentCustomMarshalerType_MarshalsCorrectly()
{
Assert.Equal(234, DifferentCustomMarshalerType("5678"));
}

public class OuterCustomMarshaler : ICustomMarshaler
{
public void CleanUpManagedData(object ManagedObj) => throw new NotImplementedException();
public void CleanUpNativeData(IntPtr pNativeData) => throw new NotImplementedException();

public int GetNativeDataSize() => throw new NotImplementedException();

public IntPtr MarshalManagedToNative(object ManagedObj) => throw new NotImplementedException();
public object MarshalNativeToManaged(IntPtr pNativeData) => throw new NotImplementedException();

public static ICustomMarshaler GetInstance(string cookie) => new InnerCustomMarshaler();

private interface ILargeInterface
{
void Method1();
void Method2();
void Method3();
void Method4();
void Method5();
void Method6();
}

private class InnerCustomMarshaler : ILargeInterface, ICustomMarshaler
{
public void Method1() => throw new InvalidOperationException();
public void Method2() => throw new InvalidOperationException();
public void Method3() => throw new InvalidOperationException();
public void Method4() => throw new InvalidOperationException();
public void Method5() => throw new InvalidOperationException();
public void Method6() => throw new InvalidOperationException();

public void CleanUpManagedData(object ManagedObj) { }
public void CleanUpNativeData(IntPtr pNativeData) => Marshal.FreeCoTaskMem(pNativeData);

public int GetNativeDataSize() => IntPtr.Size;

public IntPtr MarshalManagedToNative(object ManagedObj) => Marshal.StringToCoTaskMemAnsi("234");
public object MarshalNativeToManaged(IntPtr pNativeData) => null;
}
}

[DllImport(LibcLibrary, EntryPoint = "atoi", CallingConvention = CallingConvention.Cdecl)]
public static extern int DifferentCustomMarshalerType([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(OuterCustomMarshaler))] string str);


public static int Main(String[] args)
{
return new ICustomMarshalerTests().RunTests();
Expand Down