NativeInvoke 1.3.0
See the version list below for details.
dotnet add package NativeInvoke --version 1.3.0
NuGet\Install-Package NativeInvoke -Version 1.3.0
<PackageReference Include="NativeInvoke" Version="1.3.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="NativeInvoke" Version="1.3.0" />
<PackageReference Include="NativeInvoke"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add NativeInvoke --version 1.3.0
#r "nuget: NativeInvoke, 1.3.0"
#:package NativeInvoke@1.3.0
#addin nuget:?package=NativeInvoke&version=1.3.0
#tool nuget:?package=NativeInvoke&version=1.3.0
<img width="100%" alt="NativeInvoke banner" src="https://raw.github.com/Cheatoid/NativeInvoke/main/NativeInvoke.jpg" /> <img src="https://capsule-render.vercel.app/api?type=waving&color=0:00f7ff,100:ff00e6&height=150§ion=header&text=π+αα©TIα―EIαα―OKE+β¨&fontSize=40&fontColor=ffffff" width="100%" />
<div align="center">
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.
π Quick Installation
Install the NuGet package:
dotnet add package NativeInvoke
Or edit your .csproj to always stay up-to-date (followed by dotnet restore --no-cache):
<ItemGroup>
<PackageReference Include="NativeInvoke" Version="*"/>
</ItemGroup>
How floating versions work:
*-*: Latest version including pre-releases (e.g.,1.1.0-beta.1,2.0.0-alpha.2)*: Latest stable version only1.*: Latest stable version with major version 11.2.*: Latest stable version with major.minor 1.2
π§ 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 |
π Requirements
- C# 14 / .NET 9 or later
- Unsafe code enabled (
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>) - Roslyn source generators enabled (default in SDK-style projects)
β¨ Example Usage
See Attribute docs.
Checkout the full Example project for more!
<details>
<summary>Click here to toggle an example for <a href="https://learn.microsoft.com/en-us/windows/win32/api/utilapiset/nf-utilapiset-beep">playing a <i>beep</i> sound on Windows platform</a> (a.k.a. <code>System.Console.Beep</code>)</summary>
1. Define your native interface
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<TBool> // 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.
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.
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<BOOL> Kernel32 { get; }
}
3. Call it like a normal .NET API
Win32.Kernel32.Boop(600u, 300u);
Under the hood, NativeInvoke generates:
- A nested sealed
__Implclass implementing your (generic) interface - Static (readonly) function pointer fields (
delegate* unmanaged) - Lazy or eager symbol resolution (
NativeLibrary) - A clean property implementation using the
fieldkeyword - Thread-safe lazy initialization using .NET 9
Locktype
All without touching your container type.
</details>
π‘ 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
-
Implement default symbol name prefix and suffix -
AddEnforceBlittableandExplicitOnlyflags - Switch to
[UnmanagedCallConv]/typeof(CallConv*)for future-proofed calling conventions (MemberFunction, Swift, etc.) - Use
IndentedTextWriterfor source-code generation -
AppendGuidto generated fields (to prevent name collisions for overloaded functions) - Make unit tests
- Explore micro-optimization: IL weaver via
Fody, replace interface dispatch andDllImportcalls withcalli
π Contributing
PRs, issues, and ideas are welcome.
NativeInvoke is built for developers who want maximum performance without sacrificing clean API design.
π Support
If you like this or you are using this in your project, consider:
- Becoming a β π€©
- Spreading the word
π License
MIT - do whatever you want, just don't blame me if you calli into oblivion.
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.