https://github.com/cheatoid/nativeinvoke
Modern, interface-based, generics-capable, source-generated P/Invoke generator for .NET
https://github.com/cheatoid/nativeinvoke
csharp csharp-sourcegenerator dotnet interop pinvoke source-generator sourcegenerator
Last synced: 17 days ago
JSON representation
Modern, interface-based, generics-capable, source-generated P/Invoke generator for .NET
- Host: GitHub
- URL: https://github.com/cheatoid/nativeinvoke
- Owner: Cheatoid
- License: mit
- Created: 2026-03-09T23:12:37.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-03-13T18:28:39.000Z (about 1 month ago)
- Last Synced: 2026-03-14T02:09:00.624Z (about 1 month ago)
- Topics: csharp, csharp-sourcegenerator, dotnet, interop, pinvoke, source-generator, sourcegenerator
- Language: C#
- Homepage: https://www.nuget.org/packages/NativeInvoke
- Size: 336 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[
](https://github.com/Cheatoid/NativeInvoke) [
](https://github.com/Cheatoid/NativeInvoke)
[](https://github.com/Cheatoid/NativeInvoke/stargazers)
[](https://github.com/Cheatoid/NativeInvoke/issues)
[](https://github.com/Cheatoid/NativeInvoke/actions/workflows/build-test.yml)
[](https://github.com/Cheatoid/NativeInvoke/blob/main/LICENSE)
[](https://discord.gg/FVCeYxwWtB)
[](https://github.com/Cheatoid/NativeInvoke)
### *High-performance, source-generated P/Invoke*
NativeInvoke is a modern, zero-overhead, generics-capable P/Invoke generator for .NET.
It uses Roslyn source generation to enforce **blittable**, **function-pointer based**, **lazy-loaded** native bindings - without the runtime overhead of `DllImport`.
You write clean interfaces.
NativeInvoke generates the unsafe bits for you at compile-time.
- Cross-platform and AOT/JIT-friendly.
- No `DllImport`.
- No delegate allocation (no pinning).
- No runtime dependencies.
- No marshalling.
- No reflection.
- No dynamic codegen (dynamic IL).
- Just pure compile-time generation glue.
[
](https://github.com/Cheatoid/NativeInvoke)
## 🚀 Quick Installation
Install the NuGet package:
```bash
dotnet add package NativeInvoke
```
Or edit your `.csproj` to always stay up-to-date (followed by `dotnet restore --no-cache`):
```xml
```
How floating versions work:
- `*-*`: Latest version including pre-releases (e.g., `1.1.0-beta.1`, `2.0.0-alpha.2`)
- `*`: Latest stable version only
- `1.*`: Latest stable version with major version 1
- `1.2.*`: Latest stable version with major.minor 1.2
[
](https://github.com/Cheatoid/NativeInvoke)
## 🧠 Why NativeInvoke?
| Feature | Benefit |
|---------------------------|-----------------------------------------|
| **Source-generated** | Zero runtime overhead |
| **Function pointers** | Faster than `DllImport` |
| **Lazy-loading support** | Load symbols/functions only when needed |
| **Interface-based** | Fully mockable for testing |
| **Generics support** | Use generics in P/Invoke |
| **No static pollution** | Clean public API surface |
| **.NET 9 `Lock` support** | Modern, allocation-free synchronization |
[
](https://github.com/Cheatoid/NativeInvoke)
## 🛠 Requirements
- C# 14 / .NET 9 or later
- Unsafe code enabled (`true`)
- Roslyn source generators enabled (default in SDK-style projects)
[
](https://github.com/Cheatoid/NativeInvoke)
## ✨ Example Usage
> 📚 [**See Attribute docs**](https://github.com/Cheatoid/NativeInvoke/blob/main/NativeInvoke/NativeImportAttribute.cs).
Checkout the [**full Example project**](https://github.com/Cheatoid/NativeInvoke/tree/main/Example) for more!
Click here to toggle an example for playing a beep sound on Windows platform (a.k.a. System.Console.Beep)
### 1. Define your native interface
```csharp
global using NativeInvoke; // Import our attributes in your project
global using NIMA = NativeInvoke.NativeImportMethodAttribute;
using BOOL = int; // Win32 BOOL is 4-bytes (0=false, 1=true)
using DWORD = uint; // double-word
#if NET6_0_OR_GREATER
[System.Runtime.Versioning.SupportedOSPlatform("windows")] // Optional (for clarity)
#endif
public interface IKernel32 // Generics are supported!
where TBool : unmanaged
{
[NIMA("Beep")] // Optional; Use this attribute if you want to load a different name/ordinal,
// or override a calling convention per function (defaults to platform-specific).
TBool Boop(DWORD frequency, DWORD duration);
[NIMA(null)] // Use null or empty string to skip generation; could also omit this and set ExplicitOnly=true
void IgnoreMe();
}
```
### 2. Expose it via a `static partial` property
The property can be nested anywhere you want (class/struct/interface/record), and you can use any accessibility level you need - the generator will match your declaration.
```csharp
public static partial class Win32
{
private const string kernel32 = "kernel32";
[NativeImport(
kernel32 // Specify native library name
, EnforceBlittable = true // Whether to enforce blittable type validation (applies to all methods, can be overriden per-method)
, ExplicitOnly = false // Whether only methods explicitly marked with NIMA should be considered
, Inherited = true // Whether to consider inherited interface methods
, Lazy = false // Whether to use lazy or eager module loading
, CallingConvention = CallingConvention.StdCall // Define the default calling convention (default is platform-specific, applies to all methods, can be overriden per-method)
, SuppressGCTransition = false // Whether to suppress the GC transition (applies to all methods, can be overriden per-method)
, SymbolPrefix = "" // Define common prefix (prepended to method name unless using explicit entry point)
, SymbolSuffix = "" // Define common suffix (appended to method name unless using explicit entry point)
)]
public static partial IKernel32 Kernel32 { get; }
}
```
### 3. Call it like a normal .NET API
```csharp
Win32.Kernel32.Boop(600u, 300u);
```
Under the hood, NativeInvoke generates:
- A nested sealed `__Impl` class implementing your (generic) interface
- Static (readonly) function pointer fields (`delegate* unmanaged`)
- Lazy or eager symbol resolution (`NativeLibrary`)
- A clean property implementation using the `field` keyword
- Thread-safe lazy initialization using .NET 9 `Lock` type
All without touching your container type.
[
](https://github.com/Cheatoid/NativeInvoke)
## 💡 Future/Experiments (ToDo list)
- [ ] Support C# 9 / .NET 5 and later via `#if`; current source generator is relying on C# 14 features and .NET 9 API
- [ ] Add support for loading symbol from numeric ordinal
- [x] ~~Implement default symbol name prefix and suffix~~
- [x] ~~Add `EnforceBlittable` and `ExplicitOnly` flags~~
- [ ] Switch to `[UnmanagedCallConv]`/`typeof(CallConv*)` for future-proofed calling conventions (MemberFunction, Swift, etc.)
- [x] ~~Format generated code using Roslyn, or use `IndentedTextWriter` for source-code generation~~
- [x] ~~Append `Guid` to generated fields (to prevent name collisions for overloaded functions)~~
- [x] ~~Make unit tests~~
- [ ] Auto-generate proper page for docs and examples (maybe use GitHub io page or wiki)
- [ ] Explore micro-optimization: IL weaver via `Fody`, replace interface dispatch and `DllImport` calls with `calli`
[
](https://github.com/Cheatoid/NativeInvoke)
## 🙏 Contributing
PRs, issues, and ideas are welcome.
NativeInvoke is built for developers who want **maximum performance** without sacrificing **clean API design**.
[
](https://github.com/Cheatoid/NativeInvoke)
## 💖 Support
If you like this or you are using this in your project, consider:
- [Becoming a ⭐](https://github.com/Cheatoid/NativeInvoke/stargazers) 🤩
- Spreading the word
[
](https://github.com/Cheatoid/NativeInvoke)
## 📄 License
[MIT](https://github.com/Cheatoid/NativeInvoke/blob/main/LICENSE) - do whatever you want, just don't blame me if you `calli` into oblivion.