Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Rust Ffi

ASecurity

Design an FFI boundary meant to last — a thin translation layer with the logic in core crates, no panic across the boundary, explicit ownership on every pointer, repr(transparent) newtypes, and unsafe extern in edition 2024. Use when designing or reviewing a Rust FFI surface, when exposing a Rust library to another language, when a DLL or shared library keeps state, or when the user asks how to shape an extern function.

2 stars
0 votes
0 copies
1 views
Added 9/19/2026
developmentrustgobashapi

Works with

cliapi

Security Analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned 9/19/2026

$npx -y skills add rewrite-rs/skills --skill rust-ffi --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Rust Ffi?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Rust Ffi
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/rewrite-rs-rust-ffi/badge)](https://www.skillsdirectory.com/skills/rewrite-rs-rust-ffi)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: rust-ffi
description: Design an FFI boundary meant to last — a thin translation layer with the logic in core crates, no panic across the boundary, explicit ownership on every pointer, repr(transparent) newtypes, and unsafe extern in edition 2024. Use when designing or reviewing a Rust FFI surface, when exposing a Rust library to another language, when a DLL or shared library keeps state, or when the user asks how to shape an extern function.
---

# Rust FFI

A boundary that is meant to stay is designed, not discovered. Moving off C —
bindgen, cbindgen, and the link into an existing build — is `/port-from-c`.

## The layer only translates

Every line of business logic lives in a normal Rust crate that knows nothing
about FFI; the `extern` layer converts types, checks pointers, and calls in.
The core crate is testable with `cargo test`, the FFI layer only through a
foreign harness — logic that drifts into the boundary is logic no test reaches.

```rust
use std::ffi::{c_char, CStr};
use std::panic::catch_unwind;

// Core: the logic, in code that knows nothing about FFI.
pub struct Client {
    pub name: String,
}

impl Client {
    fn new(name: &str) -> Self {
        Client { name: name.to_owned() }
    }
}

// Boundary: translates, checks, and calls in — nothing else.
#[repr(transparent)]
pub struct MylibClient(*mut Client);

/// # Safety
/// `name` must be NUL-terminated UTF-8, or null; the check happens once,
/// here, on the way in.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn mylib_client_new(name: *const c_char) -> *mut MylibClient {
    let build = || {
        if name.is_null() { return None; }
        let name = unsafe { CStr::from_ptr(name) }.to_str().ok()?;
        Some(Box::into_raw(Box::new(Client::new(name))) as *mut MylibClient)
    };
    catch_unwind(build).ok().flatten().unwrap_or(std::ptr::null_mut())
}

/// # Safety
/// `client` must be a non-null handle from `mylib_client_new`, freed exactly once.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn mylib_client_free(client: *mut MylibClient) {
    drop(unsafe { Box::from_raw(client as *mut Client) });
}
```

## Nothing panics across the boundary

Unwinding into a foreign frame is undefined behaviour. Every `extern "C"`
entry point catches — `catch_unwind` at the boundary, and only there — and
converts the panic to an error code or an out-parameter, the one place
`/rust-errors` does not call `catch_unwind` a last resort.

## Every pointer states its ownership

Who allocated it, who frees it, how long it stays valid, and whether null is
allowed — in the signature and in the docs. A crate that exposes an
allocation exposes the matching free from the same crate; the other side
cannot free what the first side allocated. A `# Safety` section carries it —
`/rust-docs` for the wording, `/unsafe-rust` for the invariant.

## `repr` is part of the contract

`#[repr(C)]` on every struct that crosses, and `#[repr(transparent)]` on a
newtype that wraps a handle, so the wrapper is invisible on the wire and the
type safety is free on the Rust side. A default-`repr` struct has no layout
guarantee; code that reads it from the other side works until it does not.

## Isolate the state a shared library keeps

A DLL loaded twice, or loaded and unloaded, must not leave process-global
state behind. Prefer an opaque handle the caller creates, passes back, and
destroys, over module-level statics — the handle makes the lifetime explicit
and makes two instances possible.

## Naming across the boundary

Exported symbols are prefixed with the library name, because the C namespace
is flat: `mylib_client_new`, `mylib_client_free`. Inside Rust the same
function is `Client::new`; the prefix belongs to the exported symbol.

## The edition 2024 forms

`unsafe extern { }` around the declaration of a foreign function, and
`#[unsafe(no_mangle)]` on an export. Both say out loud what was always true:
declaring a foreign signature is an unsafe assertion about the other side.

## Strings and slices do not cross as they are

A Rust `&str` is not a C string, and a `String` cannot be freed by `free()`.
`CStr` and `CString` at the boundary, pointer-plus-length for slices, and the
UTF-8 validation happens once, explicitly, on the way in.

## Deferrals

Migrating an existing C codebase into Rust is `/port-from-c`, and the bindgen
and cbindgen walkthroughs live there. Whether an `unsafe` block is sound is
`/unsafe-rust`. What the safe Rust API on top should look like is
`/rust-api-design`. The `# Safety` section wording is `/rust-docs`.

## Verification

```bash
cargo test                   # the core crate, which holds the logic
cargo miri test              # for the Rust side of pointer handling that miri can see
cargo clippy --all-targets   # at the level the repo configures
```

Plus the boundary check no cargo command performs: a foreign-language test
that loads the library, exercises create-use-destroy, and runs under the
platform leak checker. An FFI surface without it is checked on one side only.

Attribution

rewrite-rsrewrite-rs
View sourceSee grades on GitHubMore from rewrite-rs →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

285172 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

10311 votes
View all in development →