用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/rudironsoni/Synaxis --skill dotnet-native-interop命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
AI-powered wiki generation for code repositories with commands, agents, and skills
Routes .NET/C# work to domain skills. Loads coding-standards for code paths.
Skill manifest management for dotnet-agent-harness. Tracks skill dependencies, conflicts, version compatibility, and provides validation and resolution tools. Triggers on: skill manifest, dependency resolution, skill compatibility, version conflicts, build manifest, validate dependencies.
基于 SOC 职业分类
正在显示 SKILL.md
| name | dotnet-native-interop |
| description | Calls native libraries via P/Invoke. LibraryImport, marshalling, cross-platform resolution. |
Platform Invoke (P/Invoke) patterns for calling native C/C++ libraries from .NET: [LibraryImport] (preferred, .NET 7+)
vs [DllImport] (legacy), struct marshalling, string marshalling, function pointer callbacks,
NativeLibrary.SetDllImportResolver for cross-platform library resolution, and platform-specific considerations for
Windows, macOS, Linux, iOS, and Android.
Version assumptions: .NET 7.0+ baseline for [LibraryImport]. [DllImport] available in all .NET versions.
NativeLibrary API available since .NET Core 3.0.
Cross-references: [skill:dotnet-native-aot] for AOT-specific P/Invoke and [LibraryImport] in publish scenarios,
[skill:dotnet-aot-architecture] for AOT-first design patterns including source-generated interop, [skill:dotnet-winui]
for CsWin32 source generator and COM interop, [skill:dotnet-aot-wasm] for WASM JavaScript interop (not native P/Invoke).
[LibraryImport] (.NET 7+) is the preferred attribute for new P/Invoke declarations. It uses source generation to
produce marshalling code at compile time, making it fully AOT-compatible and eliminating runtime codegen overhead.
[DllImport] is the legacy attribute. It relies on runtime marshalling, which may require codegen not available in AOT
scenarios. Use [DllImport] only when targeting .NET 6 or earlier, or when the SYSLIB1054 analyzer indicates
[LibraryImport] cannot handle a specific signature.
| Scenario | Use |
|---|---|
| New code targeting .NET 7+ | [LibraryImport] |
| Targeting .NET 6 or earlier | [DllImport] |
| SYSLIB1054 analyzer flags incompatibility | [DllImport] (with comment explaining why) |
| Publishing with Native AOT | [LibraryImport] (required for full AOT compat) |
using System.Runtime.InteropServices;
public static partial class NativeApi
{
[LibraryImport("mylib")]
internal static partial int ProcessData(
ReadOnlySpan<byte> input,
int length);
[LibraryImport("mylib", StringMarshalling = StringMarshalling.Utf8)]
internal static partial int OpenByName(string name);
[LibraryImport("mylib", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool CloseResource(nint handle);
}
```text
Key requirements for `[LibraryImport]`:
- Method must be `static partial` in a `partial` class
- String marshalling must be explicitly specified via `StringMarshalling` or `[MarshalAs]` ( )
- `[: ()]`
- `<>` `<>` -- `[]` ( )
### ()
```
;
{
[]
;
[]
[]
;
}
```text
The `SYSLIB1054` analyzer suggests converting `[DllImport]` to `[LibraryImport]` provides code fixes. Key changes:
Replace `[DllImport]` `[LibraryImport]`
Change ` ` to ` `
Make the containing ``
4. `` ``
5. `` ``
6. `[]` ``
```
[("", = CharSet.Unicode, SetLastError = )]
;
[]
;
```text
---
Native library names differ across platforms. Use `NativeLibrary.SetDllImportResolver` conditional compilation to handle .
Windows uses `.dll` files. The loader searches the application directory, system directories, `PATH`.
```csharp
[]
;
```text
Windows also supports omitting the extension -- the loader appends `.dll` automatically:
```csharp
[]
;
```text
macOS uses `.dylib` files; Linux uses `.so` files. The .;
```text
.NET probing order library name ``:
`foo` (exact name)
`foo.dll`, `foo.so`, `foo.dylib` (platform extension)
`libfoo`, `libfoo.so`, `libfoo.dylib` (lib prefix + extension)
iOS does allow loading libraries at runtime. Native code must be statically linked the application binary. Use `__Internal` the library name to call functions linked the main executable:
```csharp
[]
;
```csharp
For iOS, =>
<NativeReference Include=>
<Kind>Static</Kind>
<ForceLoad></ForceLoad>
</NativeReference>
</ItemGroup>
```text
Android uses `.so` files loaded the apps lib/<abi>/ directory
[]
;
```csharp
Include platform-specific `.so` files each target ABI the project:
```xml
<ItemGroup Condition=>
<AndroidNativeLibrary Include= Abi= />
<AndroidNativeLibrary Include= Abi= />
</ItemGroup>
```text
WebAssembly does support traditional P/Invoke. Native C/C++ code cannot be called via `[LibraryImport]` `[DllImport]` browser WASM. For JavaScript interop, see [skill:dotnet-aot-wasm].
---
`NativeLibrary.SetDllImportResolver` (.NET Core +) provides runtime control over library resolution. This the recommended approach cross-platform library loading name probing insufficient.
```csharp
System.Reflection;
System.Runtime.InteropServices;
NativeLibrary.SetDllImportResolver(
Assembly.GetExecutingAssembly(),
DllImportResolver);
{
(libraryName == )
{
(OperatingSystem.IsWindows())
NativeLibrary.Load(, assembly, searchPath);
(OperatingSystem.IsMacOS())
NativeLibrary.Load(, assembly, searchPath);
(OperatingSystem.IsLinux())
NativeLibrary.Load(, assembly, searchPath);
}
.Zero;
}
```text
| Scenario | Why resolver needed |
|----------|----------------------|
| Versioned `.so` = NativeLibrary.Load();
(NativeLibrary.TryLoad(, h))
{
funcPtr = NativeLibrary.GetExport(h, );
(NativeLibrary.TryGetExport(h, , fp))
{
}
NativeLibrary.Free(h);
}
```text
---
Structs passed to native code must have a well-defined memory layout. Use `[StructLayout]` to control layout alignment.
```csharp
System.Runtime.InteropServices;
[]
Point
{
X;
Y;
}
[]
ValueUnion
{
[] IntValue;
[] FloatValue;
[] DoubleValue;
}
[]
PackedHeader
{
Magic;
Length;
Version;
}
```text
**Blittable structs** (containing only primitive types sequential/ layout) are passed directly to native code without copying. Non-blittable structs require marshalling, which incurs overhead.
Blittable primitive types: ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``.
**Not blittable:** `` (marshals - `BOOL` ), `` (depends charset), ``, arrays of non-blittable types.
Specify encoding explicitly. Never rely marshalling behavior.
```csharp
[]
;
[]
;
[]
;
```text
For output buffers, use `[]` `[]` `ArrayPool` instead of `StringBuilder`:
```csharp
[]
;
[] buffer = ArrayPool<>.Shared.Rent();
{
result = GetName(buffer, buffer.Length);
name = (buffer, , result);
}
{
ArrayPool<>.Shared.Return(buffer);
}
```text
Modern .NET (.NET +) prefers function pointers over -based callbacks better performance AOT compatibility.
**Preferred: Unmanaged function pointers `[UnmanagedCallersOnly]`**
```csharp
System.Runtime.InteropServices;
[]
;
[])]
{
;
}
{
RegisterCallback(&MyCallback, .Zero);
}
```text
**Alternative: Delegate-;
[]
;
NativeCallback? s_callback;
{
s_callback = NativeCallback(MyManagedCallback);
RegisterCallbackDelegate(s_callback, .Zero);
}
{
* ;
}
```text
Use `SafeHandle` subclasses to manage native resource lifetimes instead of raw `IntPtr`/``. This prevents resource leaks use-after-free bugs.
```csharp
System.Runtime.InteropServices;
Microsoft.Win32.SafeHandles;
:
{
{ }
{
NativeApi.CloseResource(handle);
;
}
}
{
[]
;
[]
;
[]
;
}
```text
---
Map C/C++ types to .NET types carefully. Some C types have platform-dependent sizes.
| C/C++ Type | .NET Type | Size |
|------------|-----------|------|
| `int8_t` / `` | `` | |
| `uint8_t` / `unsigned ` | `` | |
| `int16_t` / `` | `` | bytes |
| `uint16_t` / `unsigned ` | `` | bytes |
| `int32_t` / `` | `` | bytes |
| `uint32_t` / `unsigned ` | `` | bytes |
| `int64_t` / ` ` | `` | bytes |
| `uint64_t` / `unsigned ` | `` | bytes |
| `` | `` | bytes |
| `` | `` | bytes |
| C/C++ Type | .NET Type | Notes |
|------------|-----------|-------|
| `size_t` / `ptrdiff_t` | `` / `` | Pointer-sized |
| `*` / pointer types | `` `*` | Pointer-sized |
| `` (C/C++) | `CLong` (.NET +) | bytes Windows, bytes Unix -bit |
| `unsigned ` | `CULong` (.NET +) | Same platform variance `` |
| Windows `BOOL` | `` | bytes ( ``) |
| Windows `BOOLEAN` | `` | |
Do use C
---
**Do use `[DllImport]` .NET + code without justification.** Use `[LibraryImport]` which generates marshalling at compile time. Only fall back to `[DllImport]` SYSLIB1054 analyzer indicates incompatibility.
**Do assume `` marshals .** .NET marshals `` a - Windows `BOOL` . Use `[MarshalAs(UnmanagedType.U1)]` C `_Bool`/``, `[MarshalAs(UnmanagedType.Bool)]` Windows `BOOL` explicitly.
**Do use C
**Do use `StringBuilder` output buffers.** `[LibraryImport]` does support `StringBuilder` at all, `[DllImport]` it allocates multiple intermediate copies. Use `[]` `[]` `ArrayPool` instead.
**Do use `[LibraryImport]` `[DllImport]` WASM.** WebAssembly does support traditional P/Invoke. For JavaScript interop WASM, see [skill:dotnet-aot-wasm].
**Do use library loading iOS.** iOS prohibits loading libraries at runtime. Use `` the library name statically linked native code.
**Do use `System.Delegate` fields interop structs.**