Official agent skill

P/Invoke and LibraryImport for .NET

by dotnet in dotnet/skills

Helps write, review and debug .NET declarations that call native C and C++ libraries, covering signatures, string marshalling, memory lifetime and SafeHandle.

OfficialMITAuto-check passedDevelopment

Install P/Invoke and LibraryImport for .NET

skills CLI
$ npx skills add dotnet/skills --skill dotnet-pinvoke -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install dotnet/skills dotnet-pinvoke --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/dotnet-advanced/skills/dotnet-pinvoke .claude/skills/dotnet-pinvoke && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
dotnet-pinvoke
GitHub stars
5.6k
Used in
1 other repo
Token cost
~4.8k tokens
SKILL.md length
1,370 words
Files
3 (incl. references)
Skills in repo
91
Repo updated
First seen
Licence
MIT

At a glance

Helps write, review and debug .NET declarations that call native C and C++ libraries, covering signatures, string marshalling, memory lifetime and SafeHandle.

  • Works in 8 steps: Choose DllImport or LibraryImport → Map Native Types to .NET Types → Write the Declaration → …
  • Writing a DllImport or LibraryImport declaration from a C or C++ header
  • SKILL.md covers When to Use This Skill, Stop Signals, Inputs and Workflow, plus 5 more sections
  • Calls dotnet

What it does

The skill picks between `DllImport` and `LibraryImport` first: `DllImport` for .NET Framework, source-generated `LibraryImport` from .NET 7 for new code, and `LibraryImport` as the only choice when native AOT is required. It asks for the native header or documentation, the target framework, the target platforms, which affect sizes of `long` and `size_t`, and who allocates and frees each buffer or handle. When the header and online docs disagree, the header wins.

Work then moves through signature mapping, string and memory handling, `SafeHandle` and cross-platform patterns, with `references/type-mapping.md` and `references/diagnostics.md` as backup. Stop signals keep it proportionate: a single function needs only the signature, existing `DllImport` code is not migrated unless asked or AOT demands it, CsWin32 is suggested only for Win32 APIs, callbacks only when function pointers are required, and a review gets a checklist instead of a rewrite. COM interop and C++/CLI are out of scope.

When your agent uses it

  • Writing a DllImport or LibraryImport declaration from a C or C++ header
  • Reviewing P/Invoke signatures for type size, calling convention or string encoding errors
  • Debugging AccessViolationException, DllNotFoundException or corruption at the native boundary
  • Migrating DllImport declarations to LibraryImport for AOT or trimming

Example prompts

  • “Write LibraryImport declarations for the functions in zstd.h targeting a recent .NET version.”
  • “Review these DllImport signatures; I get an AccessViolationException on the second call.”
  • “Wrap this C library's handle API in a SafeHandle class.”
  • “Migrate our DllImport declarations to LibraryImport so we can publish with native AOT.”

Requirements

  • The native library's C or C++ header
  • A .NET project, with .NET 7 or later for LibraryImport

Workflow steps

8 steps, taken from the step headings in SKILL.md.

  1. Choose DllImport or LibraryImport
  2. Map Native Types to .NET Types
  3. Write the Declaration
  4. Handle Strings Correctly
  5. Establish Memory Ownership
  6. Use SafeHandle for Native Handles
  7. Handle Errors
  8. Handle Callbacks (if needed)

What it can do on your machine

Read from SKILL.md and the folder at commit a660de8. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • dotnet

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • github.com
    • learn.microsoft.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

P/Invoke and LibraryImport for .NET loads about 4.8k tokens when it runs, and up to ~6.5k if it reads all its reference files. Until then it costs about 138 tokens; SKILL.md has 1,370 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~138
When it runs · the whole SKILL.md, loaded when a task matches
~4.8k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~6.5k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from dotnet/skills at commit a660de8, republished under its MIT licence (© dotnet). 1,370 words, ~4,823 tokens.

Download SKILL.mdSave it as .claude/skills/dotnet-pinvoke/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.
name
dotnet-pinvoke
description
Correctly call native (C/C++) libraries from .NET using P/Invoke and LibraryImport. Covers function signatures, string marshalling, memory lifetime, SafeHandle, and cross-platform patterns. USE FOR: writing new P/Invoke or LibraryImport declarations, reviewing or debugging existing native interop code, wrapping a C or C++ library for use in .NET, diagnosing crashes, memory leaks, or corruption at the managed/native boundary. DO NOT USE FOR: COM interop, C++/CLI mixed-mode assemblies, or pure managed code with no native dependencies.
license
MIT

.NET P/Invoke

Calling native code from .NET is powerful but unforgiving. Incorrect signatures, garbled strings, and leaked or freed memory are the most common sources of bugs — all can manifest as intermittent crashes, silent data corruption, or access violations far from the actual defect.

This skill covers both DllImport (available since .NET Framework 1.0) and LibraryImport (source-generated, .NET 7+). When targeting .NET Framework, always use DllImport. When targeting .NET 7+, prefer LibraryImport for new code. When native AOT is a requirement, LibraryImport is the only option.

When to Use This Skill

  • Writing a new [DllImport] or [LibraryImport] declaration from a C/C++ header
  • Reviewing P/Invoke signatures for correctness (type sizes, calling conventions, string encoding)
  • Wrapping an entire C library for use from .NET
  • Debugging AccessViolationException, DllNotFoundException, or silent data corruption at the native boundary
  • Migrating DllImport declarations to LibraryImport for AOT/trimming compatibility
  • Diagnosing memory leaks or heap corruption involving native handles or buffers

Stop Signals

  • Single function? Map the signature (Steps 1-3), handle strings/memory only if relevant, skip tooling and migration sections.
  • Don't migrate existing DllImport to LibraryImport unless the user asks or AOT/trimming is an explicit requirement.
  • Don't recommend CsWin32 unless the target is specifically Win32 APIs.
  • Don't generate callbacks (Step 8) unless the native API requires function pointers.
  • Review request? Use the validation checklist — don't rewrite working code.

Inputs

InputRequiredDescription
Native header or documentationYesC/C++ function signatures, struct definitions, calling conventions
Target frameworkYesDetermines whether to use DllImport or LibraryImport
Target platformsRecommendedAffects type sizes (long, size_t) and library naming
Memory ownership contractYesWho allocates and who frees each buffer or handle

Agent behavior: When documentation and native headers diverge, always trust the header. Online documentation (including official Win32 API docs) frequently omits or simplifies details about types, calling conventions, and struct layout that are critical for correct P/Invoke signatures.


Workflow

Step 1: Choose DllImport or LibraryImport
AspectDllImportLibraryImport (.NET 7+)
MechanismRuntime marshallingSource generator (compile-time)
AOT / Trim safeNoYes
String marshallingCharSet enumStringMarshalling enum
Error handlingSetLastErrorSetLastPInvokeError
Availability.NET Framework 1.0+.NET 7+ only
Step 2: Map Native Types to .NET Types

The most dangerous mappings — these cause the majority of bugs:

C / Win32 Type.NET TypeWhy
longCLong32-bit on Windows, 64-bit on 64-bit Unix. With LibraryImport, requires [assembly: DisableRuntimeMarshalling]
size_tnuint / UIntPtrPointer-sized. Use nuint on .NET 8+ and UIntPtr on earlier .NET. Never use ulong
BOOL (Win32)intNot bool — Win32 BOOL is 4 bytes
bool (C99)[MarshalAs(UnmanagedType.U1)] boolMust specify 1-byte marshal
HANDLE, HWNDSafeHandlePrefer over raw IntPtr
LPWSTR / wchar_t*stringUTF-16 on Windows (lowest cost for in strings). Avoid in cross-platform code — wchar_t width is compiler-defined (typically UTF-32 on non-Windows)
LPSTR / char*stringMust specify encoding (ANSI or UTF-8). Always requires marshalling cost for in parameters

For the complete type mapping table, struct layout, and blittable type rules, see references/type-mapping.md.

❌ NEVER use int or long for C long — it's 32-bit on Windows, 64-bit on Unix. Always use CLong. ❌ NEVER use ulong for size_t — causes stack corruption on 32-bit. Use nuint or UIntPtr. ❌ NEVER use bool without MarshalAs — the default marshal size is wrong.

Step 3: Write the Declaration

Given a C header:

c
int32_t process_records(const Record* records, size_t count, uint32_t* out_processed);

DllImport:

csharp
[DllImport("mylib")]
private static extern int ProcessRecords(
    [In] Record[] records, UIntPtr count, out uint outProcessed);

LibraryImport:

csharp
[LibraryImport("mylib")]
internal static partial int ProcessRecords(
    [In] Record[] records, nuint count, out uint outProcessed);

Calling conventions only need to be specified when targeting Windows x86 (32-bit), where Cdecl and StdCall differ. On x64, ARM, and ARM64, there is a single calling convention and the attribute is unnecessary.

Agent behavior: If you detect that Windows x86 is a target — through project properties (e.g., <PlatformTarget>x86</PlatformTarget>), runtime identifiers (e.g., win-x86), build scripts, comments, or developer instructions — flag this to the developer and recommend explicit calling conventions on all P/Invoke declarations.

csharp
// DllImport (x86 targets)
[DllImport("mylib", CallingConvention = CallingConvention.Cdecl)]

// LibraryImport (x86 targets)
[LibraryImport("mylib")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]

If the managed method name differs from the native export name, specify EntryPoint to avoid EntryPointNotFoundException:

csharp
// DllImport
[DllImport("mylib", EntryPoint = "process_records")]
private static extern int ProcessRecords(
    [In] Record[] records, UIntPtr count, out uint outProcessed);

// LibraryImport
[LibraryImport("mylib", EntryPoint = "process_records")]
internal static partial int ProcessRecords(
    [In] Record[] records, nuint count, out uint outProcessed);
Step 4: Handle Strings Correctly
  1. Know what encoding the native function expects. There is no safe default.
  2. Windows APIs: Always call the W (UTF-16) variant. The A variant needs a specific reason and explicit ANSI encoding.
  3. Cross-platform C libraries: Usually expect UTF-8.
  4. Specify encoding explicitly. Never rely on CharSet.Auto.
  5. Never introduce StringBuilder for output buffers.

❌ NEVER rely on CharSet.Auto or omit string encoding — there is no safe default.

csharp
// DllImport — Windows API (UTF-16)
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int GetModuleFileNameW(
    IntPtr hModule, [Out] char[] filename, int size);

// DllImport — Cross-platform C library (UTF-8)
[DllImport("mylib")]
private static extern int SetName(
    [MarshalAs(UnmanagedType.LPUTF8Str)] string name);

// LibraryImport — UTF-16
[LibraryImport("kernel32", StringMarshalling = StringMarshalling.Utf16,
    SetLastPInvokeError = true)]
internal static partial int GetModuleFileNameW(
    IntPtr hModule, [Out] char[] filename, int size);

// LibraryImport — UTF-8
[LibraryImport("mylib", StringMarshalling = StringMarshalling.Utf8)]
internal static partial int SetName(string name);

String lifetime warning: Marshalled strings are freed after the call returns. If native code stores the pointer (instead of copying), the lifetime must be manually managed. On Windows or .NET Framework, CoTaskMemAlloc/CoTaskMemFree is the first choice for cross-boundary ownership; on non-Windows targets, use NativeMemory APIs. The library may have its own allocator that must be used instead.

Step 5: Establish Memory Ownership

When memory crosses the boundary, exactly one side must own it — and both sides must agree.

❌ NEVER free with a mismatched allocator — Marshal.FreeHGlobal on malloc'd memory is heap corruption.

Model 1 — Caller allocates, caller frees (safest):

csharp
[LibraryImport("mylib")]
private static partial int GetName(
    Span<byte> buffer, nuint bufferSize, out nuint actualSize);

public static string GetName()
{
    Span<byte> buffer = stackalloc byte[256];
    int result = GetName(buffer, (nuint)buffer.Length, out nuint actualSize);
    if (result != 0) throw new InvalidOperationException($"Failed: {result}");
    return Encoding.UTF8.GetString(buffer[..(int)actualSize]);
}

Model 2 — Callee allocates, caller frees (common in Win32):

csharp
[LibraryImport("mylib")]
private static partial IntPtr GetVersion();
[LibraryImport("mylib")]
private static partial void FreeString(IntPtr s);

public static string GetVersion()
{
    IntPtr ptr = GetVersion();
    try { return Marshal.PtrToStringUTF8(ptr) ?? throw new InvalidOperationException(); }
    finally { FreeString(ptr); } // Must use the library's own free function
}

Critical rule: Always free with the matching allocator. Never use Marshal.FreeHGlobal or Marshal.FreeCoTaskMem on malloc'd memory.

Model 3 — Handle-based (callee allocates, callee frees): Use SafeHandle (see Step 6).

Pinning managed objects — when native code stores the pointer or runs asynchronously:

csharp
// Synchronous: use fixed
public static unsafe void ProcessSync(byte[] data)
{
    fixed (byte* ptr = data) { ProcessData(ptr, (nuint)data.Length); }
}

// Asynchronous: use GCHandle
var gcHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
// Must keep pinned until native processing completes, then call gcHandle.Free()
Show full SKILL.md (530 more words)Show less
Step 6: Use SafeHandle for Native Handles

Raw IntPtr leaks on exceptions and has no double-free protection. SafeHandle is non-negotiable.

csharp
internal sealed class MyLibHandle : SafeHandleZeroOrMinusOneIsInvalid
{
    // Required by the marshalling infrastructure to instantiate the handle.
    // Do not remove — there are no direct callers.
    private MyLibHandle() : base(ownsHandle: true) { }

    [LibraryImport("mylib", StringMarshalling = StringMarshalling.Utf8)]
    private static partial MyLibHandle CreateHandle(string config);

    [LibraryImport("mylib")]
    private static partial int UseHandle(MyLibHandle h, ReadOnlySpan<byte> data, nuint len);

    [LibraryImport("mylib")]
    private static partial void DestroyHandle(IntPtr h);

    protected override bool ReleaseHandle() { DestroyHandle(handle); return true; }

    public static MyLibHandle Create(string config)
    {
        var h = CreateHandle(config);
        if (h.IsInvalid) throw new InvalidOperationException("Failed to create handle");
        return h;
    }

    public int Use(ReadOnlySpan<byte> data) => UseHandle(this, data, (nuint)data.Length);
}

// Usage: SafeHandle is IDisposable
using var handle = MyLibHandle.Create("config=value");
int result = handle.Use(myData);
Step 7: Handle Errors
csharp
// Win32 APIs — check SetLastError
[LibraryImport("kernel32", SetLastPInvokeError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool CloseHandle(IntPtr hObject);

if (!CloseHandle(handle))
    throw new Win32Exception(Marshal.GetLastPInvokeError());

// HRESULT APIs
int hr = NativeDoWork(context);
Marshal.ThrowExceptionForHR(hr);
Step 8: Handle Callbacks (if needed)

Preferred (.NET 8+): UnmanagedCallersOnly — avoids delegates entirely, no GC lifetime risk:

csharp
[UnmanagedCallersOnly]
private static void LogCallback(int level, IntPtr message)
{
    string msg = Marshal.PtrToStringUTF8(message) ?? string.Empty;
    Console.WriteLine($"[{level}] {msg}");
}

[LibraryImport("mylib")]
private static unsafe partial void SetLogCallback(
    delegate* unmanaged<int, IntPtr, void> cb);

unsafe { SetLogCallback(&LogCallback); }

The method must be static, must not throw exceptions back to native code, and can only use blittable parameter types.

Fallback (older TFMs or when instance state is needed): delegate with rooting

csharp
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] // Only needed on Windows x86
private delegate void LogCallbackDelegate(int level, IntPtr message);

// CRITICAL: prevent delegate from being garbage collected
private static LogCallbackDelegate? s_logCallback;

public static void EnableLogging(Action<int, string> handler)
{
    s_logCallback = (level, msgPtr) =>
    {
        string msg = Marshal.PtrToStringUTF8(msgPtr) ?? string.Empty;
        handler(level, msg);
    };
    SetLogCallback(s_logCallback);
}

If native code stores the function pointer, the delegate must stay rooted for its entire lifetime. A collected delegate means a crash.

GC.KeepAlive for short-lived callbacks: When converting a delegate to a function pointer with Marshal.GetFunctionPointerForDelegate, the GC does not track the relationship between the pointer and the delegate. Use GC.KeepAlive to prevent collection before the native call completes:

csharp
var callback = new LogCallbackDelegate((level, msgPtr) =>
{
    string msg = Marshal.PtrToStringUTF8(msgPtr) ?? string.Empty;
    Console.WriteLine($"[{level}] {msg}");
});

IntPtr fnPtr = Marshal.GetFunctionPointerForDelegate(callback);
NativeUsesCallback(fnPtr);
GC.KeepAlive(callback); // prevent collection — fnPtr does not root the delegate

Cross-Platform Library Loading

Use NativeLibrary.SetDllImportResolver for complex scenarios, or conditional compilation for simple cases. Use CLong/CULong for C long/unsigned long. Note: CLong/CULong with LibraryImport requires [assembly: DisableRuntimeMarshalling].

csharp
// Trivial: use platform naming convention
// The default naming convention adds corresponding prefix and extension when
// searching the nativelibrary. The resultant file name will be mylib.dll on
// Windows, libmylib.so on Linux and libmylib.dylib on macOS.
private const string LibName = "mylib";

// Simple: conditional compilation
// WINDOWS, LINUX, MACOS are predefined only when targeting an OS-specific TFM
// (e.g., net8.0-windows). For portable TFMs (e.g., net8.0), these symbols are
// not defined — use the runtime resolver approach below instead.
#if WINDOWS
    private const string LibName = "mylib.dll";
#elif LINUX
    private const string LibName = "libmylib.so";
#elif MACOS
    private const string LibName = "libmylib.dylib";
#endif

// Complex: runtime resolver
// When targeting netstandard2.0 or other frameworks when OperatingSystem.IsXXX
// is not available, use RuntimeInformation.IsOSPlatform(OSPlatform.XXX) api.
NativeLibrary.SetDllImportResolver(typeof(MyLib).Assembly,
    (name, assembly, searchPath) =>
    {
        if (name != "mylib") return IntPtr.Zero;
        string libName = OperatingSystem.IsWindows()
            ? "mylib.dll"
            : OperatingSystem.IsMacOS()
                ? "libmylib.dylib" : "libmylib.so";
        NativeLibrary.TryLoad(libName, assembly, searchPath, out var handle);
        return handle;
    });

Migrating DllImport to LibraryImport

For codebases targeting .NET 7+, migrating provides AOT compatibility and trimming safety.

  1. Add partial to the containing class and make the method static partial
  2. Replace [DllImport] with [LibraryImport]
  3. Replace CharSet with StringMarshalling
  4. Replace SetLastError = true with SetLastPInvokeError = true
  5. Remove CallingConvention unless targeting Windows x86
  6. Build and fix SYSLIB1054–SYSLIB1057 analyzer warnings

Enable the interop analyzers:

xml
<PropertyGroup>
    <EnableTrimAnalyzer>true</EnableTrimAnalyzer>
    <EnableAotAnalyzer>true</EnableAotAnalyzer>
</PropertyGroup>

Tooling

CsWin32 (Win32 APIs)

For Win32 P/Invoke, prefer Microsoft.Windows.CsWin32 over hand-written signatures. It source-generates correct declarations from metadata. Add a NativeMethods.txt listing the APIs you need:

bash
dotnet add package Microsoft.Windows.CsWin32
CsWinRT (WinRT APIs)

For WinRT interop, use Microsoft.Windows.CsWinRT to generate .NET projections from .winmd files.

Objective Sharpie (Objective-C APIs)

For binding Objective-C libraries (macOS/iOS), use Objective Sharpie to generate initial P/Invoke and binding definitions from Objective-C headers.


Validation

Review checklist
  • Every signature matches the native header exactly (types, sizes)
  • Calling convention specified if targeting Windows x86; omitted otherwise
  • String encoding is explicit — no reliance on defaults or CharSet.Auto
  • Memory ownership is documented and matched (who allocates, who frees, with what)
  • SafeHandle used for all native handles (no raw IntPtr escaping the interop layer)
  • Delegates passed as callbacks are rooted to prevent GC collection
  • SetLastError/SetLastPInvokeError set for APIs that use OS error codes
  • Struct layout matches native (packing, alignment, field order)
  • CLong/CULong used for C long/unsigned long in cross-platform code
  • If using CLong/CULong with LibraryImport, [assembly: DisableRuntimeMarshalling] is applied
  • No bool without explicit MarshalAs — always specify UnmanagedType.Bool (4-byte) or UnmanagedType.U1 (1-byte) to ensure normalization across the language boundary.
Runnable validation steps
  1. Build with interop analyzers enabled — confirm zero SYSLIB1054–SYSLIB1057 warnings:
    xml
    <EnableTrimAnalyzer>true</EnableTrimAnalyzer>
    <EnableAotAnalyzer>true</EnableAotAnalyzer>
  2. Verify struct sizes match — for every struct crossing the boundary, assert Marshal.SizeOf<T>() equals the native sizeof
  3. Round-trip test — call the native function with known inputs and verify expected outputs
  4. Test with non-ASCII strings — pass strings containing characters outside the ASCII range to confirm encoding is correct

Reference Files

  • references/type-mapping.md — Complete native-to-.NET type mapping table, struct layout patterns, blittable type rules. Load when encountering types not covered in Step 2 above, or when working with struct layout or blittable type questions.
  • references/diagnostics.md — Common pitfalls, failure modes and recovery, debugging approach, external resources. Load when debugging an existing P/Invoke failure or reviewing interop code for correctness issues.

© dotnet, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 2 other files (references) in plugins/dotnet-advanced/skills/dotnet-pinvoke of dotnet/skills.

  • SKILL.md
  • references/diagnostics.md
  • references/type-mapping.md

Open the folder on GitHubat commit a660de8

Used in 1 other repository

We found 2 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in dotnet/skills, which our catalogue first saw on October 7, 2026.

Compare with similar skills

P/Invoke and LibraryImport for .NET next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

P/Invoke and LibraryImport for .NET compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
P/Invoke and LibraryImport for .NET this skilldotnet/skills5.6k1 repos~4.8kAutomated safety check: PassMIT
Analyze CrashDataDog/dd-trace-dotnet573—~2.6kAutomated safety check: WarnApache-2.0
Sokol Netelix22/Sokol.NET154—~2.8kAutomated safety check: PassMIT
Winapp CLIboshi-xixixi/TraeSkill275—~1.9kAutomated safety check: PassMIT
Debugging CodeJetBrains/skills3641 repos~3.8kAutomated safety check: PassNone
Qt C++ Code Reviewx-tools-author/x-tools1.1k2 repos~4.3kAutomated safety check: PassBSD-3-Clause

Similar skills

  • Analyze Crash

    DataDog/dd-trace-dotnet

    Official

    Stack Trace Crash Analysis for dd-trace-dotnet. An agent skill from DataDog/dd-trace-dotnet.

    573 GitHub stars~2.6k tokensUpdated today
    DevelopmentAuto-check: warnings
  • Sokol Net

    elix22/Sokol.NET

    Sokol.NET framework development — use for ANY work in this repo: creating or debugging examples, building/running for desktop/Android/iOS/Web, writing or compiling shaders, adding a new C/C++…

    154 GitHub stars~2.8k tokensUpdated 2 days ago
    Game DevelopmentAuto-check passed
  • Winapp CLI

    boshi-xixixi/TraeSkill

    Windows App Development CLI (winapp) for building, packaging, signing, debugging, and UI-automating Windows applications.

    275 GitHub stars~1.9k tokensUpdated 4 mo ago
    MobileAuto-check passed
  • Debugging Code

    JetBrains/skills

    Official

    A skill your agent uses for debugger-driven runtime root-cause analysis in Rider-supported solutions and projects, including .NET/C, F, VB, C++, Unity, Unreal Engine, and other GameDev or…

    364 GitHub starsUsed in 1 repo~3.8k tokens
    Game DevelopmentAuto-check passed
  • Qt C++ Code Review

    x-tools-author/x-tools

    Read-only review of Qt6 C++ code that combines a deterministic lint script with six parallel analysis agents and reports only high-confidence issues.

    1.1k GitHub starsUsed in 2 repos~4.3k tokens
    DevelopmentAuto-check passed
  • Qt Cpp Review

    Serial-Studio/Serial-Studio

    Qt6/C++ deep code review for Serial Studio. An agent skill from Serial-Studio/Serial-Studio.

    7.2k GitHub stars~4.3k tokensUpdated today
    DevelopmentAuto-check passed

More from dotnet/skills

All 91 skills in this repo
  • Official

    Resolves .NET runtime frames in Apple .ips crash logs to function names, source files and line numbers using dSYM symbols, atos and the Microsoft symbol server.

    5.6k GitHub starsUsed in 1 repo~2.4k tokens
    Auto-check passed
  • Official

    Resolves native crash frames from .NET Android tombstones to function names, source files and line numbers using BuildIds, Microsoft's symbol server and llvm-symbolizer.

    5.6k GitHub starsUsed in 1 repo~2.1k tokens
    Auto-check passed
  • Official

    Scans C# and .NET code for about 50 performance anti-patterns and reports prioritized findings with concrete fixes, at a scan depth you choose.

    5.6k GitHub starsUsed in 3 repos~3.1k tokens
    Auto-check passed
  • Official

    Statically pairs source files with test files to list code that no test references, using Roslyn for C# or tree-sitter for many languages, with no build.

    5.6k GitHub starsUsed in 1 repo~3.3k tokens
    Auto-check passed
  • Microbenchmarking

    dotnet/skills

    Official

    Activate this skill when BenchmarkDotNet (BDN) is involved in the task — creating, running, configuring, or reviewing BDN benchmarks.

    5.6k GitHub starsUsed in 3 repos~3.3k tokens
    Auto-check passed
  • Official

    Makes .NET projects compatible with Native AOT and trimming by resolving IL trim and AOT analyzer warnings through annotations rather than suppressions.

    5.6k GitHub starsUsed in 2 repos~4.2k tokens
    Auto-check passed

Works with

Categories

Questions about P/Invoke and LibraryImport for .NET

What does P/Invoke and LibraryImport for .NET do?

Helps write, review and debug .NET declarations that call native C and C++ libraries, covering signatures, string marshalling, memory lifetime and SafeHandle. NET 7 for new code, and `LibraryImport` as the only choice when native AOT is required. It asks for the native header or documentation, the target framework, the target platforms, which affect sizes of `long` and `size_t`, and who allocates and frees each buffer or handle.

When should I use P/Invoke and LibraryImport for .NET?

P/Invoke and LibraryImport for .NET fits situations like: writing a DllImport or LibraryImport declaration from a C or C++ header; reviewing P/Invoke signatures for type size, calling convention or string encoding errors; debugging AccessViolationException, DllNotFoundException or corruption at the native boundary; migrating DllImport declarations to LibraryImport for AOT or trimming.

How do I install P/Invoke and LibraryImport for .NET in Claude Code?

Run `npx skills add dotnet/skills --skill dotnet-pinvoke -a claude-code`. Or copy the skill folder (plugins/dotnet-advanced/skills/dotnet-pinvoke in dotnet/skills) into .claude/skills/dotnet-pinvoke in your project. Claude Code loads it when a task matches its description.

How do I install P/Invoke and LibraryImport for .NET in Codex?

Run `npx skills add dotnet/skills --skill dotnet-pinvoke -a codex`. Or copy the skill folder (plugins/dotnet-advanced/skills/dotnet-pinvoke in dotnet/skills) into .agents/skills/dotnet-pinvoke in your project. Codex loads it when a task matches its description.

Can I use P/Invoke and LibraryImport for .NET in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add dotnet/skills --skill dotnet-pinvoke -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/dotnet-pinvoke, .gemini/skills/dotnet-pinvoke, .github/skills/dotnet-pinvoke and .opencode/skills/dotnet-pinvoke in your project.

What does P/Invoke and LibraryImport for .NET need to run?

Going by SKILL.md and its folder, P/Invoke and LibraryImport for .NET needs the command-line tools its instructions call (dotnet). Our summary lists: The native library's C or C++ header; A .NET project, with .NET 7 or later for LibraryImport.

Does P/Invoke and LibraryImport for .NET access the network?

SKILL.md names 2 domains. As links in the text: github.com and learn.microsoft.com. This is read from the text; nothing was executed.

Is P/Invoke and LibraryImport for .NET safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does P/Invoke and LibraryImport for .NET use?

P/Invoke and LibraryImport for .NET is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does P/Invoke and LibraryImport for .NET use?

About 4.8k tokens (SKILL.md is roughly 19k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 1.7k tokens, read only when the agent opens those files.

What are the alternatives to P/Invoke and LibraryImport for .NET?

Skills that share tags, products or a category with P/Invoke and LibraryImport for .NET: Analyze Crash (DataDog/dd-trace-dotnet, 573 stars), Sokol Net (elix22/Sokol.NET, 154 stars), Winapp CLI (boshi-xixixi/TraeSkill, 275 stars) and Debugging Code (JetBrains/skills, 364 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains P/Invoke and LibraryImport for .NET?

dotnet (a GitHub organization, an official publisher) maintains it in dotnet/skills, which has 5,576 GitHub stars. The repository holds 91 skills in this directory. The repository was last updated on October 8, 2026.

Source: dotnet/skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.