{"id":19293512,"url":"https://github.com/reloaded-project/devops-rust-c-library-to-dotnet","last_synced_at":"2026-02-27T09:38:57.435Z","repository":{"id":245204299,"uuid":"817485745","full_name":"Reloaded-Project/devops-rust-c-library-to-dotnet","owner":"Reloaded-Project","description":"GitHub Action for building a C# wrapper library for a Rust library. Use with csbindgen.","archived":false,"fork":false,"pushed_at":"2025-12-15T10:45:37.000Z","size":229,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"v1-master","last_synced_at":"2025-12-18T10:58:43.093Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Reloaded-Project.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-06-19T20:19:43.000Z","updated_at":"2025-12-15T10:45:34.000Z","dependencies_parsed_at":"2024-11-09T22:35:24.676Z","dependency_job_id":"75b9281c-e936-4281-bf33-672d21deb339","html_url":"https://github.com/Reloaded-Project/devops-rust-c-library-to-dotnet","commit_stats":null,"previous_names":["reloaded-project/devops-rust-c-library-to-dotnet"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Reloaded-Project/devops-rust-c-library-to-dotnet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reloaded-Project%2Fdevops-rust-c-library-to-dotnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reloaded-Project%2Fdevops-rust-c-library-to-dotnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reloaded-Project%2Fdevops-rust-c-library-to-dotnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reloaded-Project%2Fdevops-rust-c-library-to-dotnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Reloaded-Project","download_url":"https://codeload.github.com/Reloaded-Project/devops-rust-c-library-to-dotnet/tar.gz/refs/heads/v1-master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reloaded-Project%2Fdevops-rust-c-library-to-dotnet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29889526,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T08:34:21.514Z","status":"ssl_error","status_checked_at":"2026-02-27T08:32:38.035Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T22:35:15.786Z","updated_at":"2026-02-27T09:38:57.411Z","avatar_url":"https://github.com/Reloaded-Project.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/Reloaded-Project/devops-rust-c-library-to-dotnet\" target=\"_blank\"\u003e\n    \u003cimg src=\"assets/reloaded-logo.png\" alt=\"reloaded Logo\" width=\"100\"/\u003e\n  \u003c/a\u003e\n\n  \u003ch1 align=\"center\"\u003eReloaded Deploy Rust C Library to .NET Wrapper Action\u003c/h1\u003e\n\n  \u003cp\u003e\n    \u003ca href=\"LICENSE\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/License-MIT-blue.svg\" alt=\"License\"\u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\nThe `devops-rust-c-library-to-dotnet` GitHub Action builds and packages a .NET library that\nacts as a wrapper for a Rust library with C exports.\n\nIt works by taking the artifact outputs of [devops-rust-lightweight-binary@v1][rust-lightweight-library]\naction (usually named `C-Library-*`), and extracting the native (`.dll`, `.so`, `.dylib`) binaries\nfrom them.\n\nThese are then placed in appropriate `runtime` folders in the .NET library project, which is then\nbuilt and packed into a NuGet package.\n\n## An Example\n\nSuppose you run the following step in your GitHub workflow:\n\n```yaml\ntest-library-build:\n  strategy:\n    matrix:\n      include:\n        - os: ubuntu-latest\n          target: x86_64-unknown-linux-gnu\n          use-pgo: true\n          use-cross: false\n        - os: ubuntu-latest\n          target: i686-unknown-linux-gnu\n          use-pgo: true\n          use-cross: false\n        - os: ubuntu-latest\n          target: aarch64-unknown-linux-gnu\n          use-pgo: true # x64 host to aarch64 simulated guest via cross\n          use-cross: true\n        - os: ubuntu-latest\n          target: armv7-unknown-linux-gnueabihf\n          use-pgo: true # x64 host to armv7 simulated guest via cross\n          use-cross: true\n        - os: windows-latest\n          target: x86_64-pc-windows-msvc\n          use-pgo: true\n          use-cross: false\n        - os: windows-latest\n          target: i686-pc-windows-msvc\n          use-pgo: true\n          use-cross: false\n        - os: windows-latest\n          target: aarch64-pc-windows-msvc\n          use-pgo: false # no virtualization support (proprietary OS)\n          use-cross: false\n        - os: macos-13 # x86\n          target: x86_64-apple-darwin\n          use-pgo: true\n          use-cross: false\n        - os: macos-14 # M1\n          target: aarch64-apple-darwin\n          use-pgo: true\n          use-cross: false\n  runs-on: ${{ matrix.os }}\n  steps:\n    - name: Checkout Test Repository\n      uses: actions/checkout@v4\n      with:\n        repository: Sewer56/prs-rs\n        ref: d08599ed5473616f57d57a0966939e1a5dbda9b4\n    - name: Test Library Build\n      uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test\n      with:\n        crate-name: prs-rs\n        target: ${{ matrix.target }}\n        use-pgo: ${{ matrix.use-pgo }}\n        use-cross: ${{ matrix.use-cross }}\n        features: \"c-exports\"\n        build-library: true\n        upload-artifacts: true\n```\n\nThis will produce the following artifacts: \n\n- `C-Library-aarch64-apple-darwin-c-exports.zip`\n- `C-Library-aarch64-pc-windows-msvc-c-exports.zip`\n- `C-Library-aarch64-unknown-linux-gnu-c-exports.zip`\n- `C-Library-armv7-unknown-linux-gnueabihf-c-exports.zip`\n- `C-Library-i686-unknown-linux-gnu-c-exports.zip`\n- `C-Library-i686-pc-windows-msvc-c-exports.zip`\n- `C-Library-x86_64-apple-darwin-c-exports.zip`\n- `C-Library-x86_64-pc-windows-msvc-c-exports.zip`\n- `C-Library-x86_64-unknown-linux-gnu-c-exports.zip`\n\n\nRunning this action with the following configuration:\n\n```yaml\n- name: Build and Package .NET Library\n  uses: Reloaded-Project/devops-rust-c-library-to-dotnet@v1\n  with:\n    csharp-project-path: bindings/csharp\n    install-dotnet: true\n```\n\nWill perform the following.\n\n1. Install .NET, if needed.\n2. Download artifacts and insert them into appropriate subdirectories of `bindings/csharp`\n\n```\nbindings/csharp/\n├── MyLibrary.csproj\n├── runtimes/\n│   ├── linux-x64/\n│   │   └── native/\n│   │       └── libmylibrary.so\n│   ├── win-x64/\n│   │   └── native/\n│   │       └── mylibrary.dll\n│   └── osx-x64/\n│       └── native/\n│           └── libmylibrary.dylib\n└── // Other C# files and directories\n```\n\n3. Build \u0026 Pack the Project into a NuGet package.\n4. Upload the NuGet package as an artifact, with name specified in `nuget-artifact-name`.\n\n## Setting up a new Repository\n\nThis action was made to be used in conjunction with the excellent [Cysharp/csbindgen][csbindgen]\nbinding generator by Yoshifumi Kawai (neuecc).\n\nTypical usage is as follows, [prs-rs][prs-rs] will be used as an example.\n\n1. Set up `csbindgen` to generate C# bindings for your Rust library.\n\n```rust\n// build.rs in Rust project\nfn main() {\n    csbindgen::Builder::default()\n        .input_extern_file(\"src/exports.rs\")\n        .csharp_dll_name(\"prs_rs\")\n        .csharp_class_accessibility(\"public\")\n        .csharp_namespace(\"prs_rs.Net.Sys\")\n        .generate_csharp_file(\"bindings/csharp/NativeMethods.g.cs\")\n        .unwrap();\n}\n```\n\n```csharp\n// Ensure DLL is loaded when requested.\nclass Init\n{\n    [ModuleInitializer]\n    internal static void RegisterImportResolver()\n    {\n        // .NET Core 3.X and above only!!\n        NativeLibrary.SetDllImportResolver(typeof(NativeMethods).Assembly, NativeMethods.DllImportResolver);\n    }\n}\n\n/// \u003csummary/\u003e\npublic static unsafe partial class NativeMethods\n{\n    // https://docs.microsoft.com/en-us/dotnet/standard/native-interop/cross-platform\n    // Library path will search\n    // win =\u003e __DllName, __DllName.dll\n    // linux, osx =\u003e __DllName.so, __DllName.dylib\n    internal static IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)\n    {\n        if (libraryName == __DllName)\n        {\n            var dllName = __DllName;\n            var path = \"runtimes/\";\n            var extension = \"\";\n\n            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))\n            {\n                path += \"win-\";\n                extension = \".dll\";\n            }\n            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))\n            {\n                path += \"osx-\";\n                extension = \".dylib\";\n                dllName = \"lib\" + dllName;\n            }\n            else\n            {\n                path += \"linux-\";\n                extension = \".so\";\n                dllName = \"lib\" + dllName;\n            }\n\n            if (RuntimeInformation.ProcessArchitecture == Architecture.X86)\n            {\n                path += \"x86\";\n            }\n            else if (RuntimeInformation.ProcessArchitecture == Architecture.X64)\n            {\n                path += \"x64\";\n            }\n            else if (RuntimeInformation.ProcessArchitecture == Architecture.Arm)\n            {\n                path += \"arm\";\n            }\n            else if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)\n            {\n                path += \"arm64\";\n            }\n\n            path += \"/native/\" + dllName + extension;\n            try\n            {\n                return NativeLibrary.Load(Path.Combine(AppContext.BaseDirectory, path), assembly, searchPath);\n            }\n            catch (DllNotFoundException)\n            {\n                return NativeLibrary.Load(Path.Combine(AppContext.BaseDirectory, dllName + extension));\n            }\n        }\n\n        return IntPtr.Zero;\n    }\n}\n```\n\nFor more information, read the [full documentation for csbindgen][csbindgen].\n\n2. Use the [Example Above](#an-example) to set up a workflow.\n\n## Typical Workflow\n\nOnce set up, usage is very easy. In fact, it's automatic.\n\n1. You add 1 or more C exports to your Rust library.\n2. When you next build, `csbindgen` will automatically update `NativeMethods.g.cs`.\n\nYou're done. Everything else is automated.\n\n## Inputs\n\n| Input                 | Required | Default           | Description                                                         |\n| --------------------- | -------- | ----------------- | ------------------------------------------------------------------- |\n| `artifact-prefix`     | No       | `C-Library-`      | Prefix for the artifact names to download                           |\n| `csharp-project-path` | No       | `bindings/csharp` | Path to the C# project directory                                    |\n| `install-dotnet`      | No       | `false`           | If true, installs the .NET SDK with specified version               |\n| `dotnet-version`      | No       | `8.0.x`           | Version of the .NET SDK to install                                  |\n| `nuget-artifact-name` | No       | `NuGet-Package`   | Name for the NuGet artifact                                         |\n\n## Supported Targets\n\nThis action automatically injects the following target platforms:\n\n- Windows (x86_64, i686, aarch64)\n- Linux (x86_64, i686, aarch64, armv7)\n- macOS (x86_64, aarch64)\n- Android (x86_64, aarch64, armv7, i686)\n- iOS (aarch64, x86_64)\n\nBasically everything upstream .NET CoreCLR supports, and some hypothetical platforms.\n\n## Output\n\nThe action generates a NuGet package containing the .NET librarys.\nThe NuGet package is uploaded as an artifact with the name specified by the\n`nuget-artifact-name` input.\n\n## Contributing\n\nContributions are welcome! If you encounter any issues or have suggestions for improvements, please\nopen an issue or submit a pull request in this repository.\n\n## License\n\nThis project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.\n\n[rust-lightweight-library]: https://github.com/Reloaded-Project/devops-rust-lightweight-binary\n[csbindgen]: https://github.com/Cysharp/csbindgen\n[prs-rs]: https://github.com/Sewer56/prs-rs","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freloaded-project%2Fdevops-rust-c-library-to-dotnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freloaded-project%2Fdevops-rust-c-library-to-dotnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freloaded-project%2Fdevops-rust-c-library-to-dotnet/lists"}