Skip to content

Commit 4742a5d

Browse files
committed
Merge branches 'master' and 'master' of https://github.com/OpenByteDev/netcorehost
2 parents c2f2dc8 + ac3ad8e commit 4742a5d

11 files changed

Lines changed: 230 additions & 45 deletions

File tree

.github/workflows/ci.yml

Lines changed: 63 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
env:
3939
NETCOREHOST_TEST_NETCORE_VERSION: net${{ matrix.dotnet }}
4040
steps:
41-
- uses: actions/checkout@v4
41+
- uses: actions/checkout@v6
4242

4343
- name: Uninstall .NET SDKs
4444
run: ./.github/scripts/uninstall-dotnet-${{ matrix.os }}
@@ -52,7 +52,7 @@ jobs:
5252
run: dotnet --info
5353

5454
- name: Install latest ${{ matrix.toolchain }}
55-
uses: dtolnay/rust-toolchain@stable
55+
uses: dtolnay/rust-toolchain@master
5656
with:
5757
target: ${{ matrix.target }}
5858
toolchain: ${{ matrix.toolchain }}
@@ -64,30 +64,22 @@ jobs:
6464
- name: Test
6565
run: cargo test --target ${{ matrix.target }} --all-targets --no-fail-fast --no-default-features --features "nethost-download $("net" + "${{ matrix.dotnet }}".replace(".", "_"))" -- --nocapture
6666
shell: pwsh
67-
68-
cross:
67+
68+
arm-build:
6969
runs-on: ubuntu-latest
7070
strategy:
7171
fail-fast: false
7272
matrix:
7373
toolchain: ["beta"]
7474
target: ["aarch64-unknown-linux-gnu", "armv7-unknown-linux-gnueabihf"]
75-
7675
steps:
77-
- uses: actions/checkout@v4
78-
79-
- name: Install latest ${{ matrix.toolchain }}
80-
uses: dtolnay/rust-toolchain@stable
81-
with:
82-
target: ${{ matrix.target }}
83-
toolchain: ${{ matrix.toolchain }}
84-
85-
- name: Install cross
86-
# temporary fix, see cross-rs/cross#1561
87-
run: RUSTFLAGS="" cargo install cross --git https://github.com/cross-rs/cross
88-
89-
- name: Build
90-
run: cross build --target ${{ matrix.target }}
76+
- uses: actions/checkout@v6
77+
- name: Install latest rust nightly for ${{ matrix.target }}
78+
uses: dtolnay/rust-toolchain@nightly
79+
with:
80+
targets: ${{ matrix.target }}
81+
- name: Check main crate
82+
run: cargo check --target ${{ matrix.target }} --all-features
9183

9284
examples:
9385
runs-on: ubuntu-latest
@@ -96,17 +88,58 @@ jobs:
9688
toolchain: ["beta"]
9789
example: ["run-app", "run-app-with-args", "call-managed-function", "passing-parameters", "return-string-from-managed"]
9890
steps:
99-
- uses: actions/checkout@v4
91+
- uses: actions/checkout@v6
10092
- name: Install latest ${{ matrix.toolchain }}
101-
uses: dtolnay/rust-toolchain@stable
93+
uses: dtolnay/rust-toolchain@master
10294
with:
103-
toolchain: ${{ matrix.toolchain }}
95+
toolchain: ${{ matrix.toolchain }}
10496
- name: Build .NET project for '${{ matrix.example }}'
10597
working-directory: ./examples/${{ matrix.example }}/ExampleProject
10698
run: dotnet build
10799
- name: Run example '${{ matrix.example }}'
108100
run: cargo run --example ${{ matrix.example }}
109-
101+
102+
nightly-examples:
103+
runs-on: windows-latest
104+
strategy:
105+
matrix:
106+
toolchain: ["nightly"]
107+
example: ["call-native-function"]
108+
steps:
109+
- uses: actions/checkout@v6
110+
- name: Install latest ${{ matrix.toolchain }}
111+
uses: dtolnay/rust-toolchain@master
112+
with:
113+
toolchain: ${{ matrix.toolchain }}
114+
- name: Build .NET project for '${{ matrix.example }}'
115+
working-directory: ./examples/${{ matrix.example }}/ExampleProject
116+
run: dotnet build
117+
- name: Run example '${{ matrix.example }}'
118+
env:
119+
RUSTFLAGS: -Z export-executable-symbols
120+
run: cargo run --example ${{ matrix.example }}
121+
122+
hack:
123+
runs-on: ubuntu-latest
124+
steps:
125+
- uses: actions/checkout@v6
126+
- name: Install latest nightly
127+
uses: dtolnay/rust-toolchain@nightly
128+
- name: cargo install cargo-hack
129+
uses: taiki-e/install-action@cargo-hack
130+
- name: cargo hack
131+
run: cargo hack --feature-powerset check
132+
133+
machete:
134+
runs-on: ubuntu-latest
135+
steps:
136+
- uses: actions/checkout@v6
137+
- name: Install latest nightly
138+
uses: dtolnay/rust-toolchain@nightly
139+
- name: cargo install cargo-machete
140+
uses: taiki-e/install-action@cargo-machete
141+
- run: cargo machete
142+
110143
documentation:
111144
runs-on: ${{ matrix.os }}-latest
112145
strategy:
@@ -115,11 +148,9 @@ jobs:
115148
- os: ubuntu
116149
- os: windows
117150
steps:
118-
- uses: actions/checkout@v4
151+
- uses: actions/checkout@v6
119152
- name: Install latest nightly
120-
uses: dtolnay/rust-toolchain@stable
121-
with:
122-
toolchain: nightly
153+
uses: dtolnay/rust-toolchain@nightly
123154
- name: Generate documentation
124155
run: cargo doc --all-features
125156
- name: Install cargo-deadlinks
@@ -135,12 +166,11 @@ jobs:
135166
- os: ubuntu
136167
- os: windows
137168
steps:
138-
- uses: actions/checkout@v4
169+
- uses: actions/checkout@v6
139170
- name: Install latest nightly
140-
uses: dtolnay/rust-toolchain@stable
171+
uses: dtolnay/rust-toolchain@nightly
141172
with:
142-
toolchain: nightly
143-
components: clippy
173+
components: clippy
144174

145175
- name: Clippy check
146176
run: cargo clippy --all-features
@@ -153,11 +183,10 @@ jobs:
153183
- os: ubuntu
154184
- os: windows
155185
steps:
156-
- uses: actions/checkout@v4
186+
- uses: actions/checkout@v6
157187
- name: Install latest nightly
158-
uses: dtolnay/rust-toolchain@stable
188+
uses: dtolnay/rust-toolchain@nightly
159189
with:
160-
toolchain: nightly
161190
components: rustfmt
162191

163192
- name: Format check

.github/workflows/rerun.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Auto-rerun (Uninstall .NET SDKs failure)
2+
3+
on:
4+
workflow_run:
5+
workflows: ["CI"]
6+
types: [completed]
7+
8+
permissions:
9+
actions: write
10+
contents: read
11+
12+
jobs:
13+
rerun_if_uninstall_dotnet_failed:
14+
if: >
15+
github.event.workflow_run.conclusion == 'failure' &&
16+
github.event.workflow_run.run_attempt < 5
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- name: Decide whether to rerun
21+
id: decide
22+
env:
23+
GH_TOKEN: ${{ github.token }}
24+
REPO: ${{ github.repository }}
25+
RUN_ID: ${{ github.event.workflow_run.id }}
26+
STEP_NAME: "Uninstall .NET SDKs"
27+
shell: bash
28+
run: |
29+
set -euo pipefail
30+
31+
# Fetch jobs + steps for the failed workflow run
32+
jobs_json="$(gh api -H "Accept: application/vnd.github+json" \
33+
"/repos/${REPO}/actions/runs/${RUN_ID}/jobs?per_page=100")"
34+
35+
# Check whether the specific step failed
36+
if echo "$jobs_json" | jq -e --arg step "$STEP_NAME" '
37+
.jobs[].steps[]? | select(.name == $step and .conclusion == "failure")
38+
' >/dev/null; then
39+
echo "rerun=true" >> "$GITHUB_OUTPUT"
40+
echo "Detected failure in step: $STEP_NAME"
41+
else
42+
echo "rerun=false" >> "$GITHUB_OUTPUT"
43+
echo "No failure in step '$STEP_NAME' detected; not rerunning."
44+
fi
45+
46+
- name: Rerun failed jobs
47+
if: steps.decide.outputs.rerun == 'true'
48+
env:
49+
GH_TOKEN: ${{ github.token }}
50+
REPO: ${{ github.repository }}
51+
RUN_ID: ${{ github.event.workflow_run.id }}
52+
shell: bash
53+
run: |
54+
gh run rerun "$RUN_ID" -R "$REPO" --failed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.vs
2+
obj/
3+
bin/
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Library</OutputType>
5+
<TargetFramework>net10.0</TargetFramework>
6+
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
7+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
8+
</PropertyGroup>
9+
10+
</Project>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.31521.260
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{20FFF50B-3B22-484C-BB76-E34082C70A8C}") = "ExampleProject", "ExampleProject.csproj", "{FF3FD3DA-8A6E-4BB1-805E-9207F740F9A0}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{FF3FD3DA-8A6E-4BB1-805E-9207F740F9A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{FF3FD3DA-8A6E-4BB1-805E-9207F740F9A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{FF3FD3DA-8A6E-4BB1-805E-9207F740F9A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{FF3FD3DA-8A6E-4BB1-805E-9207F740F9A0}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {BDCBB934-B852-4DE8-BE74-1B677720FF0A}
24+
EndGlobalSection
25+
EndGlobal
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using System.Runtime.Versioning;
4+
using System.Text;
5+
6+
namespace ExampleProject {
7+
public static class Program {
8+
[UnmanagedCallersOnly]
9+
public static unsafe int IndirectIncrement1(int n) {
10+
var module = NativeLibrary.GetMainProgramHandle();
11+
var rusty_increment = (delegate* unmanaged<int, int>)NativeLibrary.GetExport(module, "rusty_increment");
12+
return rusty_increment(n);
13+
}
14+
15+
[SupportedOSPlatform("windows")]
16+
[UnmanagedCallersOnly]
17+
public static int IndirectIncrement2(int n) {
18+
return rusty_increment(n);
19+
}
20+
21+
[SupportedOSPlatform("windows")]
22+
[DllImport("call-native-function.exe", ExactSpelling = true)]
23+
public static extern int rusty_increment(int n);
24+
}
25+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Note that this example requires the unstable rustc flag "-Z export-executable-symbols"
2+
3+
use netcorehost::{nethost, pdcstr};
4+
5+
#[no_mangle]
6+
pub extern "system" fn rusty_increment(n: i32) -> i32 {
7+
println!("Called rusty increment with {n}");
8+
n + 1
9+
}
10+
11+
fn main() {
12+
let hostfxr = nethost::load_hostfxr().unwrap();
13+
let context = hostfxr.initialize_for_runtime_config(pdcstr!("examples/call-native-function/ExampleProject/bin/Debug/net10.0/ExampleProject.runtimeconfig.json")).unwrap();
14+
let delegate_loader = context
15+
.get_delegate_loader_for_assembly(pdcstr!(
16+
"examples/call-native-function/ExampleProject/bin/Debug/net10.0/ExampleProject.dll"
17+
))
18+
.unwrap();
19+
20+
let increment1 = delegate_loader
21+
.get_function_with_unmanaged_callers_only::<fn(i32) -> i32>(
22+
pdcstr!("ExampleProject.Program, ExampleProject"),
23+
pdcstr!("IndirectIncrement1"),
24+
)
25+
.unwrap();
26+
#[cfg(windows)]
27+
let increment2 = delegate_loader
28+
.get_function_with_unmanaged_callers_only::<fn(i32) -> i32>(
29+
pdcstr!("ExampleProject.Program, ExampleProject"),
30+
pdcstr!("IndirectIncrement2"),
31+
)
32+
.unwrap();
33+
34+
assert_eq!(2, increment1(1));
35+
#[cfg(windows)]
36+
assert_eq!(3, increment2(2));
37+
}

examples/return-string-from-managed/main.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![warn(unsafe_op_in_unsafe_fn)]
2+
// See also call-native-function example
23

34
use core::slice;
45
use std::{
@@ -72,7 +73,6 @@ fn print_string_from_csharp_using_unmanaged_alloc(delegate_loader: &AssemblyDele
7273
.unwrap();
7374
FREE_H_GLOBAL
7475
.set(free_h_global)
75-
.ok()
7676
.expect("string interop already init");
7777

7878
// actual usage
@@ -131,7 +131,6 @@ fn print_string_from_csharp_using_gc_handle(delegate_loader: &AssemblyDelegateLo
131131
.unwrap();
132132
FREE_GC_HANDLE_STRING
133133
.set(free_gc_handle_string)
134-
.ok()
135134
.expect("string interop already init");
136135

137136
let get_string_data_offset = delegate_loader
@@ -172,7 +171,7 @@ impl GcHandleString {
172171
let unmarked_ptr = (self.0 as usize & !1usize) as *const *const u16;
173172
let string_ptr = unsafe { *unmarked_ptr };
174173
let string_data_offset = *STRING_DATA_OFFSET.get().expect("string interop not init");
175-
return unsafe { string_ptr.byte_add(string_data_offset) }.cast::<u16>();
174+
unsafe { string_ptr.byte_add(string_data_offset) }.cast::<u16>()
176175
}
177176
pub fn len(&self) -> usize {
178177
// read the length of the string which is stored in front of the data.

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![cfg_attr(feature = "nightly", feature(try_trait_v2, maybe_uninit_slice))]
1+
#![cfg_attr(feature = "nightly", feature(try_trait_v2))]
22
#![cfg_attr(feature = "doc-cfg", feature(doc_cfg))]
33
#![warn(clippy::pedantic, clippy::cargo, unsafe_op_in_unsafe_fn, missing_docs)]
44
#![allow(

src/nethost.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ pub enum LoadHostfxrError {
112112
}
113113

114114
const unsafe fn maybe_uninit_slice_assume_init_ref<T>(slice: &[MaybeUninit<T>]) -> &[T] {
115+
// not yet stable as const
115116
#[cfg(feature = "nightly")]
116117
unsafe {
117118
slice.assume_init_ref()

0 commit comments

Comments
 (0)