Skip to content

Commit a7dc093

Browse files
committed
Create repro for dotnet/coreclr#19654
1 parent c0c51f8 commit a7dc093

File tree

10 files changed

+213
-2
lines changed

10 files changed

+213
-2
lines changed

tests/src/Interop/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ add_subdirectory(DllImportAttribute/ExeFile)
6161
add_subdirectory(DllImportAttribute/FileNameContainDot)
6262
add_subdirectory(DllImportAttribute/Simple)
6363
add_subdirectory(ExecInDefAppDom)
64+
add_subdirectory(ICustomMarshaler/MultipleALCs)
6465

6566
if(WIN32)
6667
add_subdirectory(PInvoke/Attributes/LCID)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
cmake_minimum_required (VERSION 2.6)
2+
project (CustomMarshalersALCNative)
3+
include_directories(${INC_PLATFORM_DIR})
4+
set(SOURCES CustomMarshalersALCNative.cpp )
5+
6+
# add the executable
7+
add_library (CustomMarshalersALCNative SHARED ${SOURCES})
8+
target_link_libraries(CustomMarshalersALCNative ${LINK_LIBRARIES_ADDITIONAL})
9+
10+
# add the install targets
11+
install (TARGETS CustomMarshalersALCNative DESTINATION bin)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.IO;
7+
using System.Linq;
8+
using System.Reflection;
9+
using System.Runtime.Loader;
10+
11+
class CustomLoadContext : AssemblyLoadContext
12+
{
13+
private string unmanagedDirectory;
14+
15+
internal CustomLoadContext(string unmanagedDirectory)
16+
{
17+
this.unmanagedDirectory = unmanagedDirectory;
18+
}
19+
20+
protected override Assembly Load(AssemblyName assemblyName)
21+
{
22+
string assemblyPath = Path.Combine(".", assemblyName.Name) + ".dll";
23+
if (File.Exists(assemblyPath))
24+
{
25+
return LoadFromAssemblyPath(assemblyPath);
26+
}
27+
28+
return Default.LoadFromAssemblyName(assemblyName);
29+
}
30+
31+
protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
32+
{
33+
string unmanagedDllPath = Directory.EnumerateFiles(
34+
unmanagedDirectory,
35+
$"{unmanagedDllName}.*").Concat(
36+
Directory.EnumerateFiles(
37+
unmanagedDirectory,
38+
$"lib{unmanagedDllName}.*"))
39+
.FirstOrDefault();
40+
41+
if (unmanagedDllPath != null)
42+
{
43+
return this.LoadUnmanagedDllFromPath(unmanagedDllPath);
44+
}
45+
46+
return base.LoadUnmanagedDll(unmanagedDllName);
47+
}
48+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Runtime.InteropServices;
9+
10+
public class WrappedString
11+
{
12+
public WrappedString(string str)
13+
{
14+
_str = str;
15+
}
16+
17+
internal string _str;
18+
}
19+
20+
public class WrappedStringCustomMarshaler : ICustomMarshaler
21+
{
22+
private static readonly WrappedStringCustomMarshaler instance = new WrappedStringCustomMarshaler();
23+
24+
public void CleanUpManagedData(object ManagedObj) { }
25+
public void CleanUpNativeData(IntPtr pNativeData) { Marshal.ZeroFreeCoTaskMemAnsi(pNativeData); }
26+
27+
public int GetNativeDataSize() => IntPtr.Size;
28+
29+
public IntPtr MarshalManagedToNative(object ManagedObj) => Marshal.StringToCoTaskMemAnsi(((WrappedString)ManagedObj)._str);
30+
public object MarshalNativeToManaged(IntPtr pNativeData) => new WrappedString(Marshal.PtrToStringAnsi(pNativeData));
31+
32+
public static ICustomMarshaler GetInstance(string cookie) => instance;
33+
}
34+
35+
public class CustomMarshalerTest
36+
{
37+
[DllImport("CustomMarshalersALCNative", CharSet = CharSet.Ansi)]
38+
public static extern int NativeParseInt([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(WrappedStringCustomMarshaler))] WrappedString str);
39+
40+
public int ParseInt(string str)
41+
{
42+
return NativeParseInt(new WrappedString(str));
43+
}
44+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
4+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
5+
<PropertyGroup>
6+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
7+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
8+
<SchemaVersion>2.0</SchemaVersion>
9+
<ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
10+
<OutputType>library</OutputType>
11+
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
12+
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
13+
</PropertyGroup>
14+
<!-- Default configurations to help VS understand the configurations -->
15+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
16+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
17+
<ItemGroup>
18+
<CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
19+
<Visible>False</Visible>
20+
</CodeAnalysisDependentAssemblyPaths>
21+
</ItemGroup>
22+
<ItemGroup>
23+
<Compile Include="CustomMarshaler.cs" />
24+
</ItemGroup>
25+
<ItemGroup>
26+
</ItemGroup>
27+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
28+
</Project>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#include <stdlib.h>
6+
#include <xplatform.h>
7+
8+
9+
extern "C" int DLL_EXPORT STDMETHODCALLTYPE NativeParseInt(LPCSTR str)
10+
{
11+
return atoi(str);
12+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
4+
<Import Project="../../Interop.settings.targets" />
5+
<PropertyGroup>
6+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
7+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
8+
<SchemaVersion>2.0</SchemaVersion>
9+
<ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
10+
<OutputType>Exe</OutputType>
11+
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
12+
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
13+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
14+
</PropertyGroup>
15+
<!-- Default configurations to help VS understand the configurations -->
16+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
17+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
18+
<ItemGroup>
19+
<CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
20+
<Visible>False</Visible>
21+
</CodeAnalysisDependentAssemblyPaths>
22+
</ItemGroup>
23+
<ItemGroup>
24+
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
25+
</ItemGroup>
26+
<ItemGroup>
27+
<Compile Include="RunInALC.cs" />
28+
<Compile Include="CustomLoadContext.cs" />
29+
</ItemGroup>
30+
<ItemGroup>
31+
<ProjectReference Include="CMakeLists.txt" />
32+
<ProjectReference Include="CustomMarshalerInALC.csproj" />
33+
</ItemGroup>
34+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
35+
<PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
36+
</Project>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.IO;
7+
using System.Linq;
8+
using System.Reflection;
9+
using System.Runtime.Loader;
10+
using TestLibrary;
11+
12+
public class RunInALC
13+
{
14+
public static int Main(string[] args)
15+
{
16+
Run();
17+
Run();
18+
return 100;
19+
}
20+
21+
static void Run()
22+
{
23+
string currentAssemblyDirectory = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath);
24+
var context = new CustomLoadContext(currentAssemblyDirectory);
25+
Assembly inContextAssembly = context.LoadFromAssemblyPath(Path.Combine(currentAssemblyDirectory, "CustomMarshalerInALC.dll"));
26+
Type inContextType = inContextAssembly.GetType("CustomMarshalerTest");
27+
object instance = Activator.CreateInstance(inContextType);
28+
MethodInfo parseIntMethod = inContextType.GetMethod("ParseInt", BindingFlags.Instance | BindingFlags.Public);
29+
Assert.AreEqual(1234, (int)parseIntMethod.Invoke(instance, new object[]{"1234"}));
30+
}
31+
}

tests/src/Interop/ICustomMarshaler/ICustomMarshaler.csproj renamed to tests/src/Interop/ICustomMarshaler/Primitives/ICustomMarshaler.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
2525
</ItemGroup>
2626
<ItemGroup>
27-
<Compile Include="ICustomMarshaler.cs" />
28-
<Compile Include="..\common\XunitBase.cs" />
27+
<Compile Include="RunInALC.cs" />
2928
</ItemGroup>
3029
<ItemGroup>
30+
<ProjectReference Include="CustomMarshalersInALC.csproj" />
3131
</ItemGroup>
3232
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
3333
<PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>

0 commit comments

Comments
 (0)