Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.

Commit 0a37ad7

Browse files
authored
Add native library sample (#6645)
* fix nit in StaticLibrary test (#4987) * add README documentation on building native libraries (#4987) * Move documentation for building native libraries to samples * Fix static library build * Add sources for NativeLibrary sample
1 parent 764a7b3 commit 0a37ad7

File tree

8 files changed

+102
-5
lines changed

8 files changed

+102
-5
lines changed

Documentation/how-to-build-and-run-ilcompiler-in-console-shell-prompt.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ From the shell/command prompt, issue the following commands to generate the nati
7575

7676
For CoreRT debug build on Windows, add an extra `/p:AdditionalCppCompilerFlags=/MTd` argument.
7777

78-
## Disabling Native Compilation
78+
## Disabling Native Compilation ##
7979

8080
Native compilation can be disabled during publishing by adding an extra `/p:NativeCompilationDuringPublish=false` argument.
8181

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ This repo contains the .NET Core runtime optimized for ahead of time compilation
33

44
## Try Our Samples
55

6-
If you would like to give CoreRT a try, we publish daily snapshots of CoreRT to MyGet. Using CoreRT is as simple as adding a new package reference to your .NET Core project and publishing it. Check out one of our samples: a "[Hello World](samples/HelloWorld)" console app, a simple [ASP.NET Core](samples/WebApi/) app, or a [MonoGame](samples/MonoGame/) game. The `README.md` file in each sample's directory will guide you through the process step by step.
6+
If you would like to give CoreRT a try, we publish daily snapshots of CoreRT to MyGet. Using CoreRT is as simple as adding a new package reference to your .NET Core project and publishing it. Check out one of our samples: a "[Hello World](samples/HelloWorld)" console app, a simple [ASP.NET Core](samples/WebApi/) app, a [MonoGame](samples/MonoGame/) game or a [native library](samples/NativeLibrary). The `README.md` file in each sample's directory will guide you through the process step by step.
77

88
## Platform Support
99

samples/NativeLibrary/Class1.cs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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.Runtime.InteropServices;
7+
8+
namespace NativeLibrary
9+
{
10+
public class Class1
11+
{
12+
[NativeCallable(EntryPoint = "add", CallingConvention = CallingConvention.StdCall)]
13+
public static int Add(int a, int b)
14+
{
15+
return a + b;
16+
}
17+
}
18+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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+
namespace System.Runtime.InteropServices
6+
{
7+
[AttributeUsage(AttributeTargets.Method)]
8+
public sealed class NativeCallableAttribute : Attribute
9+
{
10+
public string EntryPoint;
11+
public CallingConvention CallingConvention;
12+
public NativeCallableAttribute() { }
13+
}
14+
}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="Microsoft.DotNet.ILCompiler" Version="1.0.0-alpha-*" />
9+
</ItemGroup>
10+
11+
</Project>

samples/NativeLibrary/README.md

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Building Native Libraries with CoreRT
2+
3+
This document will guide you through building native libraries that can be consumed by other programming languages with CoreRT. CoreRT can build static libraries that can be linked at compile time or shared libraries that are required at runtime.
4+
5+
## Create .NET Core Class Library project with CoreRT support
6+
7+
Create a .NET Core class library project using `dotnet new console -o NativeLibrary` and follow the [Hello world](../HelloWorld/README.md) sample instruction to add CoreRT support to it.
8+
9+
## Building static libraries
10+
11+
```bash
12+
> dotnet publish /p:NativeLib=Static -r <RID> -c <Configuration>
13+
```
14+
15+
where `<Configuration>` is your project configuration (such as Debug or Release) and `<RID>` is the runtime identifier (one of win-x64, linux-x64, osx-x64). For example, if you want to publish a release configuration of your library for a 64-bit version of Windows the command would look like:
16+
17+
```bash
18+
> dotnet publish /p:NativeLib=Static -r win-x64 -c release
19+
```
20+
21+
The above command will drop a static library (Windows `.lib`, OSX/Linux `.a`) in `./bin/[configuration]/netstandard2.0/[RID]/publish/` folder and will have the same name as the folder in which your source file is present.
22+
23+
## Building shared libraries
24+
25+
```bash
26+
> dotnet publish /p:NativeLib=Shared -r <RID> -c <Configuration>
27+
```
28+
29+
The above command will drop a shared library (Windows `.dll`, OSX `.dylib`, Linux `.so`) in `./bin/[configuration]/netstandard2.0/[RID]/publish/` folder and will have the same name as the folder in which your source file is present. Building shared libraries on Linux is currently non-functional, see [#4988](https://github.com/dotnet/corert/issues/4988).
30+
31+
## Exporting methods
32+
33+
For a C# method in the native library to be consumable by external programs, it has to be explicitly exported using the `[NativeCallable]` attribute. First define the `NativeCallable` class in your project, see [here](https://github.com/dotnet/corert/blob/master/tests/src/Simple/SharedLibrary/NativeCallable.cs). The local definition of the `NativeCallable` is a temporary workaround that will go away once the attribute is added to the official .NET Core public surface.
34+
35+
Next, apply the attribute to the method, specifying the `EntryPoint` and `CallingConvention` properties:
36+
37+
```csharp
38+
[NativeCallable(EntryPoint = "add", CallingConvention = CallingConvention.StdCall)]
39+
public static int Add(int a, int b)
40+
{
41+
return a + b;
42+
}
43+
```
44+
45+
After the native library library is built, the above C# `Add` method will be exported as a native `add` function to consumers of the library. Here are some limitations to consider when deciding what managed method to export:
46+
47+
* Exported methods have to be static.
48+
* Exported methods can only naturally accept or return primitives or value types (i.e structs), they have to marshal all reference type arguments.
49+
* Exported methods cannot be called from regular managed C# code, an exception will be thrown.
50+
* Exported methods cannot use regular C# exception handling, they should return error codes instead.
51+
52+
## References
53+
54+
Real-world example of using CoreRT and Rust: https://medium.com/@chyyran/calling-c-natively-from-rust-1f92c506289d

src/BuildIntegration/Microsoft.NETCore.Native.Publish.targets

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777

7878
</Target>
7979

80-
<Target Name="CopyNativePdb" Condition="'$(DebugType)' != 'None' and '$(TargetOS)' == 'Windows_NT'" AfterTargets="Publish">
80+
<Target Name="CopyNativePdb" Condition="'$(DebugType)' != 'None' and '$(TargetOS)' == 'Windows_NT' and $(NativeLib) != 'Static'" AfterTargets="Publish">
8181
<!-- dotnet CLI produces managed debug symbols - substitute with those we generated during native compilation -->
8282
<Delete Files="$(PublishDir)\$(TargetName).pdb"/>
8383
<Copy SourceFiles="$(NativeOutputPath)$(TargetName).pdb" DestinationFolder="$(PublishDir)" />

tests/src/Simple/StaticLibrary/StaticLibrary.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@
4444
</ItemGroup>
4545

4646
<Exec Command="$(CppCompiler) @(NativeRunnerCompilerArg, ' ') $(NativeBinary) @(NativeRunnerLinkerArg, ' ')" Condition="'$(OS)' != 'Windows_NT'" />
47-
<WriteLinesToFile File="$(NativeIntermediateOutputPath)SharedLibrary.cl.rsp" Lines="@(NativeRunnerCompilerArg)" Overwrite="true" Condition="'$(OS)' == 'Windows_NT'"/>
48-
<Exec Command="$(CppCompiler) @&quot;$(NativeIntermediateOutputPath)SharedLibrary.cl.rsp&quot;" Condition="'$(OS)' == 'Windows_NT'" />
47+
<WriteLinesToFile File="$(NativeIntermediateOutputPath)StaticLibrary.cl.rsp" Lines="@(NativeRunnerCompilerArg)" Overwrite="true" Condition="'$(OS)' == 'Windows_NT'"/>
48+
<Exec Command="$(CppCompiler) @&quot;$(NativeIntermediateOutputPath)StaticLibrary.cl.rsp&quot;" Condition="'$(OS)' == 'Windows_NT'" />
4949
</Target>
5050

5151
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), SimpleTest.targets))\SimpleTest.targets" />

0 commit comments

Comments
 (0)