Skip to content

Commit

Permalink
Add disabled test project for function pointers.
Browse files Browse the repository at this point in the history
  • Loading branch information
AaronRobinsonMSFT committed Jul 2, 2020
1 parent 56ad025 commit 2bc49a5
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/coreclr/tests/src/baseservices/callconvs/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
project (NativeFunctions)
include_directories(${INC_PLATFORM_DIR})

add_library (NativeFunctions SHARED NativeFunctions.cpp)

# add the install targets
install (TARGETS NativeFunctions DESTINATION bin)
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

.assembly extern System.Runtime
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 5:0:0:0
}
.assembly extern System.Runtime.InteropServices
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 5:0:0:0
}
.assembly CallFunctionPointers
{
.hash algorithm 0x00008004
.ver 1:0:0:0
}
.module CallFunctionPointers.dll

.class public auto ansi abstract sealed beforefieldinit CallFunctionPointers
extends [System.Runtime]System.Object
{
.method public hidebysig static int32 CallUnmanagedIntInt(void* p, int32 b) cil managed
{
.maxstack 2
ldarg.1
ldarg.0
calli unmanaged int32(int32)
ret
}

.method public hidebysig static int32 CallUnmanagedCdeclIntInt(void* p, int32 b) cil managed
{
.maxstack 2
ldarg.1
ldarg.0
calli unmanaged cdecl int32(int32)
ret
}

.method public hidebysig static int32 CallUnmanagedStdcallIntInt(void* p, int32 b) cil managed
{
.maxstack 2
ldarg.1
ldarg.0
calli unmanaged stdcall int32(int32)
ret
}

.method public hidebysig static char CallUnmanagedCharChar(void* p, char b) cil managed
{
.maxstack 2
ldarg.1
ldarg.0
calli unmanaged char(char)
ret
}

.method public hidebysig static char CallUnmanagedCdeclCharChar(void* p, char b) cil managed
{
.maxstack 2
ldarg.1
ldarg.0
calli unmanaged cdecl char(char)
ret
}

.method public hidebysig static char CallUnmanagedStdcallCharChar(void* p, char b) cil managed
{
.maxstack 2
ldarg.1
ldarg.0
calli unmanaged stdcall char(char)
ret
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.IL">
<PropertyGroup>
<OutputType>library</OutputType>
</PropertyGroup>
<ItemGroup>
<Compile Include="CallFunctionPointers.il" />
</ItemGroup>
</Project>
53 changes: 53 additions & 0 deletions src/coreclr/tests/src/baseservices/callconvs/NativeFunctions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <platformdefines.h>

namespace
{
int DoubleIntImpl(int a)
{
return a * 2;
}
}

extern "C" DLL_EXPORT int DoubleInt(int a)
{
return DoubleIntImpl(a);
}

extern "C" DLL_EXPORT int __cdecl DoubleIntCdecl(int a)
{
return DoubleIntImpl(a);
}

extern "C" DLL_EXPORT int __stdcall DoubleIntStdcall(int a)
{
return DoubleIntImpl(a);
}

#include <cwctype>

namespace
{
WCHAR ToUpperImpl(WCHAR a)
{
return (WCHAR)std::towupper(a);
}
}

extern "C" DLL_EXPORT WCHAR ToUpper(WCHAR a)
{
return ToUpperImpl(a);
}

extern "C" DLL_EXPORT WCHAR __cdecl ToUpperCdecl(WCHAR a)
{
return ToUpperImpl(a);
}

extern "C" DLL_EXPORT WCHAR __stdcall ToUpperStdcall(WCHAR a)
{
return ToUpperImpl(a);
}
107 changes: 107 additions & 0 deletions src/coreclr/tests/src/baseservices/callconvs/TestCallingConventions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;

using TestLibrary;

unsafe class Program
{
class NativeFunctions
{
public const string Name = nameof(NativeFunctions);

public static string GetFileName()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return $"{Name}.dll";

if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return $"lib{Name}.so";

if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return $"lib{Name}.dylib";

throw new PlatformNotSupportedException();
}

public static string GetFullPath()
{
Assembly assembly = Assembly.GetExecutingAssembly();
string directory = Path.GetDirectoryName(assembly.Location);
return Path.Combine(directory, GetFileName());
}
}

static void BlittableFunctionPointers()
{
Console.WriteLine($"Running {nameof(BlittableFunctionPointers)}...");

IntPtr mod = NativeLibrary.Load(NativeFunctions.GetFullPath());

const int a = 7;
const int expected = a * 2;
{
var cb = NativeLibrary.GetExport(mod, "DoubleInt").ToPointer();
Assert.Throws<NotImplementedException>(() => CallFunctionPointers.CallUnmanagedIntInt(cb, a));
}

{
var cb = NativeLibrary.GetExport(mod, "DoubleIntCdecl").ToPointer();
int b = CallFunctionPointers.CallUnmanagedCdeclIntInt(cb, a);
Assert.AreEqual(b, expected);
}

{
var cb = NativeLibrary.GetExport(mod, "DoubleIntStdcall").ToPointer();
int b = CallFunctionPointers.CallUnmanagedStdcallIntInt(cb, a);
Assert.AreEqual(b, expected);
}
}

static void NonblittableFunctionPointers()
{
Console.WriteLine($"Running {nameof(NonblittableFunctionPointers)}...");

IntPtr mod = NativeLibrary.Load(NativeFunctions.GetFullPath());

const char a = 'i';
const char expected = 'I';
{
var cb = NativeLibrary.GetExport(mod, "ToUpper").ToPointer();
Assert.Throws<NotImplementedException>(() => CallFunctionPointers.CallUnmanagedCharChar(cb, a));
}

{
var cb = NativeLibrary.GetExport(mod, "ToUpperCdecl").ToPointer();
var b = CallFunctionPointers.CallUnmanagedCdeclCharChar(cb, a);
Assert.AreEqual(b, expected);
}

{
var cb = NativeLibrary.GetExport(mod, "ToUpperStdcall").ToPointer();
var b = CallFunctionPointers.CallUnmanagedStdcallCharChar(cb, a);
Assert.AreEqual(b, expected);
}
}

static int Main(string[] doNotUse)
{
try
{
BlittableFunctionPointers();
NonblittableFunctionPointers();
}
catch (Exception e)
{
Console.WriteLine($"Test Failure: {e}");
return 101;
}

return 100;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

<!-- Disable test until we get new IL build tools -->
<CLRTestTargetUnsupported>true</CLRTestTargetUnsupported>
</PropertyGroup>
<ItemGroup>
<Compile Include="TestCallingConventions.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="CMakeLists.txt" />
<ProjectReference Include="CallFunctionPointers.ilproj" />
<ProjectReference Include="$(TestSourceDir)Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
</ItemGroup>
</Project>

0 comments on commit 2bc49a5

Please sign in to comment.