add-api

5
0
Source

Add new C# APIs to SkiaSharp by wrapping Skia C++ functionality. Structured 6-phase workflow: C++ analysis → C API creation → submodule commits → binding generation → C# wrapper → testing. Triggers: - Issue classified as "New API" (after fetching and classification) - Direct request: "add DrawFoo method", "expose SkSurface::draw", "wrap sk_foo_bar" - Keywords: "add API", "expose function", "wrap method", "create binding for"

Install

mkdir -p .claude/skills/add-api && curl -L -o skill.zip "https://mcp.directory/api/skills/download/2293" && unzip -o skill.zip -d .claude/skills/add-api && rm skill.zip

Installs to .claude/skills/add-api

About this skill

Add API Skill

⚠️ Branch Protection (COMPLIANCE REQUIRED)

🛑 NEVER commit directly to protected branches. This is a policy violation.

RepositoryProtected BranchesRequired Action
SkiaSharp (parent)mainCreate feature branch first
externals/skia (submodule)main, skiasharpCreate feature branch first

BEFORE making any changes, create feature branches in BOTH repos:

# Step 1: Create branch in SkiaSharp repo
git checkout -b dev/issue-NNNN-description

# Step 2: Create branch in submodule (REQUIRED for C API changes)
cd externals/skia
git checkout -b dev/issue-NNNN-description
cd ../..

❌ NEVER Do These

ShortcutConsequence
Commit directly to main or skiasharp branchesPolicy violation — blocks PR, requires revert
Edit *.generated.cs manuallyOverwrites on next generation; binding mismatch
Skip generator after C API changeC# bindings won't match C API
Skip native build after C API changeEntryPointNotFoundException at runtime — tests fail
Skip testsCan't verify functionality works
Skip tests because they failUnacceptable — fix the issue, don't skip
Commit C API without staging submoduleParent repo won't use your changes
Use externals-download after modifying C APIDownloaded natives don't have your new functions

Workflow Overview

1. Analyze C++ API  →  Find in Skia headers, identify pointer type
2. Add C API        →  Header + impl in externals/skia/
3. Commit Submodule →  Commit IN submodule, then stage in parent
4. Generate         →  Run pwsh ./utils/generate.ps1 (MANDATORY)
5. Add C# Wrapper   →  Validate params, call P/Invoke
6. Build Native     →  dotnet cake --target=externals-{platform} (MANDATORY)
7. Test             →  Run tests — must PASS (MANDATORY)

👉 Detailed checklists: references/checklists.md 👉 Troubleshooting: references/troubleshooting.md


Phase 1: Analyze C++ API

Find the C++ API in Skia headers and identify:

  1. Pointer type — determines C# wrapper pattern:

    • Raw (T*) → owns: false
    • Owned → DisposeNative() deletes
    • Ref-counted (sk_sp<T>) → ISKReferenceCounted or ISKNonVirtualReferenceCounted
  2. Error handling — returns null/bool? throws?

  3. Parameters — primitives, references, pointers, const-ness

👉 See ../../../documentation/memory-management.md#pointer-type-decision-tree


Phase 2: Add C API

Location: externals/skia/include/c/ (header) and externals/skia/src/c/ (impl)

// Header (sk_canvas.h)
SK_C_API void sk_canvas_draw_circle(sk_canvas_t* canvas, float cx, float cy, 
                                     float radius, const sk_paint_t* paint);

// Implementation (sk_canvas.cpp)
void sk_canvas_draw_circle(sk_canvas_t* canvas, float cx, float cy,
                           float radius, const sk_paint_t* paint) {
    AsCanvas(canvas)->drawCircle(cx, cy, radius, *AsPaint(paint));
}

Conversion macros: AsType() unwraps, ToType() wraps. Use sk_ref_sp() for ref-counted params, .release() for ref-counted returns.


Phase 3: Commit Submodule

🛑 CRITICAL — This is where changes get lost

# Step 1: Commit IN the submodule
cd externals/skia
git config user.email "you@example.com"  # first time only
git config user.name "Your Name"             # first time only
git add include/c/sk_*.h src/c/sk_*.cpp
git commit -m "Add sk_foo_bar to C API"

# Step 2: Stage submodule in parent
cd ../..  # Back to repo root
git add externals/skia

# Step 3: Verify
git status
# Must show: modified: externals/skia (new commits)

Phase 4: Generate Bindings

🛑 MANDATORY — Never skip, never edit generated files manually

pwsh ./utils/generate.ps1
git diff binding/SkiaSharp/SkiaApi.generated.cs  # verify new function appears

Phase 5: Add C# Wrapper

Location: binding/SkiaSharp/SK*.cs

// Factory method — returns null on failure
public static SKImage FromPixels(SKImageInfo info, SKData data, int rowBytes)
{
    if (data == null)
        throw new ArgumentNullException(nameof(data));
    var cinfo = SKImageInfoNative.FromManaged(ref info);
    return GetObject(SkiaApi.sk_image_new_raster_data(&cinfo, data.Handle, (IntPtr)rowBytes));
}

// Instance method
public void DrawCircle(float cx, float cy, float radius, SKPaint paint)
{
    if (paint == null)
        throw new ArgumentNullException(nameof(paint));
    SkiaApi.sk_canvas_draw_circle(Handle, cx, cy, radius, paint.Handle);
}

Rules: Validate nulls, factory→null on fail, constructor→throw on fail, use overloads not defaults (ABI stability).


Phase 6: Build & Test

🛑 MANDATORY — You modified the C API, so you MUST build the native library

Step 1: Build Native Library (REQUIRED)

Since you added/modified C API functions in Phase 2, you MUST rebuild the native library before testing. The pre-built natives from externals-download do not contain your new functions.

# macOS (Apple Silicon)
dotnet cake --target=externals-macos --arch=arm64

# macOS (Intel)
dotnet cake --target=externals-macos --arch=x64

# Windows (x64)
dotnet cake --target=externals-windows --arch=x64

# Linux (requires Docker)
dotnet cake --target=externals-linux --arch=x64

⚠️ Native builds take 10-30 minutes. Only build for platforms you can test on.

Step 2: Write Tests

[SkippableFact]
public void DrawCircleWorks()
{
    using var surface = SKSurface.Create(new SKImageInfo(100, 100));
    using var canvas = surface.Canvas;
    using var paint = new SKPaint { Color = SKColors.Red };
    
    canvas.DrawCircle(50, 50, 25, paint);
    
    using var image = surface.Snapshot();
    Assert.NotNull(image);
}

Step 3: Run Tests

dotnet build binding/SkiaSharp/SkiaSharp.csproj
dotnet test tests/SkiaSharp.Tests.Console/SkiaSharp.Tests.Console.csproj

🛑 Tests MUST PASS. Do not skip tests. Do not claim completion if tests fail.

Skipping tests is only acceptable for hardware limitations (no GPU, no screen attached). EntryPointNotFoundException means you forgot to build the native library — go back to Step 1.

Tests must pass before claiming completion.

More by mono

View all →

release-publish

mono

Publish SkiaSharp packages and finalize the release. Use when user says "publish X", "finalize X", "tag X", or "finish release X". This is the FINAL step - after release-testing passes. Publishes to NuGet.org, creates tag, GitHub release, and closes milestone. Triggers: "publish the release", "push to nuget", "create github release", "tag the release", "close the milestone", "annotate release notes", "testing passed what's next", "finalize 3.119.2", "release is ready".

40

release-testing

mono

Run integration tests to verify SkiaSharp NuGet packages work correctly before publishing. Use when user asks to: - Test/verify packages before release - Run integration tests - Test on specific device (iPad, iPhone, Android emulator, Mac, Windows) - Verify SkiaSharp rendering works - Check if packages are ready for publishing - Run smoke/console/blazor/maui tests - Continue with release - Test version X Triggers: "test the release", "verify packages", "run tests on iPad", "check ios tests", "test mac catalyst", "run android tests", "continue", "test 3.119.2-preview.2".

00

release-branch

mono

Create a release branch for SkiaSharp. Use when user says "release X", "start release X", "create release branch for X", "I want to release", or "release now". This is the FIRST step of releasing - creates branch and pushes to trigger CI. Can auto-detect next preview version from main branch.

10

bug-fix

mono

Fix bugs in SkiaSharp C# bindings. Structured workflow for investigating, fixing, and testing bug reports. Triggers: Crash, exception, AccessViolationException, incorrect output, wrong behavior, memory leak, disposal issues, "fails", "broken", "doesn't work", "investigate issue", "fix issue", "look at #NNNN", any GitHub issue number referencing a bug. For adding new APIs, use `add-api` skill instead.

200

api-docs

mono

Write and review XML API documentation for SkiaSharp following .NET guidelines. Triggers: "document class", "add XML docs", "write XML documentation", "add triple-slash comments", "review documentation quality", "check docs for errors", "fix doc issues", "fill in missing docs", "remove To be added placeholders", API documentation requests.

30

You might also like

flutter-development

aj-geddes

Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.

269784

drawio-diagrams-enhanced

jgtolentino

Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.

203415

godot

bfollington

This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.

184271

nano-banana-pro

garg-aayush

Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.

206231

ui-ux-pro-max

nextlevelbuilder

"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."

165195

rust-coding-skill

UtakataKyosui

Guides Claude in writing idiomatic, efficient, well-structured Rust code using proper data modeling, traits, impl organization, macros, and build-speed best practices.

163173

Stay ahead of the MCP ecosystem

Get weekly updates on new skills and servers.