AdaskoTheBeAsT.Interop.Unmanaged 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package AdaskoTheBeAsT.Interop.Unmanaged --version 1.0.0
                    
NuGet\Install-Package AdaskoTheBeAsT.Interop.Unmanaged -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AdaskoTheBeAsT.Interop.Unmanaged" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AdaskoTheBeAsT.Interop.Unmanaged" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="AdaskoTheBeAsT.Interop.Unmanaged" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add AdaskoTheBeAsT.Interop.Unmanaged --version 1.0.0
                    
#r "nuget: AdaskoTheBeAsT.Interop.Unmanaged, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package AdaskoTheBeAsT.Interop.Unmanaged@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=AdaskoTheBeAsT.Interop.Unmanaged&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=AdaskoTheBeAsT.Interop.Unmanaged&version=1.0.0
                    
Install as a Cake Tool

AdaskoTheBeAsT.Interop.Unmanaged

NuGet License: MIT

🚀 A robust, type-safe, and memory-efficient .NET library for loading and managing unmanaged DLLs with zero hassle!

Why This Library?

Working with native DLLs in .NET can be tricky - memory leaks, crashes, and platform-specific quirks. This library provides a battle-tested, safe, and elegant wrapper around Windows LoadLibrary, GetProcAddress, and FreeLibrary APIs.

✨ Key Features

  • 🛡️ Memory Safe - Uses SafeHandle pattern to prevent resource leaks
  • 🔒 Type Safe - Strongly-typed delegate mapping for native functions
  • High Performance - Minimal overhead with optimized P/Invoke
  • 🎯 Developer Friendly - Simple, intuitive API that just works
  • 🔧 Flexible - Support for custom calling conventions and generic delegates
  • 📦 Multi-Framework - Supports .NET Standard 2.0, .NET 8.0, and .NET 9.0
  • 🧪 Production Ready - Analyzed by 20+ code quality tools

Installation

dotnet add package AdaskoTheBeAsT.Interop.Unmanaged

Or via Package Manager:

Install-Package AdaskoTheBeAsT.Interop.Unmanaged

Quick Start

Basic Usage

using AdaskoTheBeAsT.Interop.Unmanaged;

// Define your native function signature
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int Add(int a, int b);

// Load the DLL and get the function
using var library = new UnmanagedLibrary("MyNative.dll");
var addFunction = library.GetUnmanagedFunction<Add>("add");

if (addFunction != null)
{
    int result = addFunction(5, 3); // result = 8
    Console.WriteLine($"Result: {result}");
}

Advanced: Custom Load Flags

using AdaskoTheBeAsT.Interop.Unmanaged;

// Load with custom search paths
var flags = LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 
          | LoadLibraryFlags.LOAD_LIBRARY_SEARCH_SYSTEM32;

using var library = new UnmanagedLibrary(@"C:\MyLibs\custom.dll", flags);
var myFunc = library.GetUnmanagedFunction<MyDelegate>("MyFunction");

Static Helper Methods

// Load library without wrapper
var handle = UnmanagedLibrary.LoadLibrary("kernel32.dll");

// Get function from handle
var func = UnmanagedLibrary.GetUnmanagedFunction<MyDelegate>(handle, "GetVersion");

// Clean up when done
UnmanagedLibrary.FreeLibrary(handle);

Generic Delegates with Custom Calling Conventions

// Get function pointer for delegate
var ptr = UnmanagedLibrary.GetFunctionPointerForDelegate(myCallback, out var binder);

// Create delegate from function pointer with custom calling convention
var del = UnmanagedLibrary.GetDelegateForFunctionPointer<MyDelegate>(
    ptr, 
    CallingConventions.Standard
);

API Overview

Core Classes

UnmanagedLibrary

Main class for loading and managing native DLLs.

// Constructor
UnmanagedLibrary(string fileName, LoadLibraryFlags flags = ...)

// Get function as delegate
TDelegate? GetUnmanagedFunction<TDelegate>(string functionName)

// Static helpers
static SafeLibraryHandle LoadLibrary(string fileName, LoadLibraryFlags flags)
static void FreeLibrary(SafeLibraryHandle handle)
static TDelegate? GetUnmanagedFunction<TDelegate>(SafeLibraryHandle handle, string functionName)
SafeLibraryHandle

Thread-safe handle wrapper that ensures proper cleanup.

LoadLibraryFlags

Comprehensive enum of Windows LoadLibraryEx flags for fine-grained control over DLL loading behavior.

DelegatePin

Utility struct for pinning delegates in memory to prevent garbage collection during native callbacks.

Common Use Cases

Loading a 3rd Party Native Library

using var lib = new UnmanagedLibrary("opencv_world.dll");
var cvVersion = lib.GetUnmanagedFunction<GetVersionDelegate>("cvGetVersion");

Platform-Specific DLL Loading

#if WINDOWS
var flags = LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 
          | LoadLibraryFlags.LOAD_LIBRARY_SEARCH_SYSTEM32;
using var lib = new UnmanagedLibrary("native_win.dll", flags);
#elif LINUX
// Use DllImport or different interop mechanism
#endif

Extracting Resources from DLLs

// Load DLL as data file without executing code
var flags = LoadLibraryFlags.LOAD_LIBRARY_AS_DATAFILE;
using var lib = new UnmanagedLibrary("resource.dll", flags);
// Extract resources here

Error Handling

The library throws meaningful exceptions with context:

try
{
    using var lib = new UnmanagedLibrary("missing.dll");
}
catch (Win32Exception ex)
{
    // "Failed to load library 'missing.dll'."
    Console.WriteLine($"Error: {ex.Message}");
    Console.WriteLine($"Native Error Code: {ex.NativeErrorCode}");
}

try
{
    using var lib = new UnmanagedLibrary(null!);
}
catch (ArgumentException ex)
{
    // "Value cannot be null or whitespace. (Parameter 'fileName')"
    Console.WriteLine($"Error: {ex.Message}");
}

Performance Tips

  1. Reuse library instances - Keep the UnmanagedLibrary instance alive if you need multiple function calls
  2. Cache delegates - Store retrieved delegates instead of calling GetUnmanagedFunction repeatedly
  3. Use static methods - For one-off calls, static helper methods avoid object allocation
// ❌ Bad - Repeated loading
for (int i = 0; i < 1000; i++)
{
    using var lib = new UnmanagedLibrary("my.dll");
    var func = lib.GetUnmanagedFunction<MyDelegate>("MyFunc");
    func?.Invoke();
}

// ✅ Good - Load once, use many times
using var lib = new UnmanagedLibrary("my.dll");
var func = lib.GetUnmanagedFunction<MyDelegate>("MyFunc");
for (int i = 0; i < 1000; i++)
{
    func?.Invoke();
}

Security Considerations

  • The library uses SuppressUnmanagedCodeSecurity for performance - only load trusted DLLs
  • Always validate file paths before loading to prevent DLL hijacking attacks
  • Use LOAD_LIBRARY_SEARCH_* flags to control DLL search paths and prevent loading from untrusted locations
  • Dispose library instances promptly to prevent holding locks on DLL files

Requirements

  • .NET Standard 2.0 or higher
  • .NET 8.0 or higher
  • .NET 9.0 or higher
  • Windows OS (uses Windows API under the hood)

Contributing

Contributions are welcome! This project maintains high code quality standards with:

  • 20+ static analyzers (StyleCop, Roslynator, SonarAnalyzer, etc.)
  • Treat warnings as errors
  • Nullable reference types enabled
  • Comprehensive documentation required

License

This project is licensed under the MIT License - see the LICENSE file for details.

Credits

Developed with ❤️ by Adam Pluciński


⭐ If this library saved you time, give it a star on GitHub!

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on AdaskoTheBeAsT.Interop.Unmanaged:

Package Downloads
AdaskoTheBeAsT.WkHtmlToX

AdaskoTheBeAsT.WkHtmlToX c# wrapper

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0 233 4/20/2026
2.0.0 105 4/7/2026
1.0.0 204 11/23/2025