<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ffi on</title><link>/tags/ffi/</link><description>Recent content in Ffi on</description><generator>Hugo</generator><language>en</language><lastBuildDate>Fri, 04 Jul 2025 16:50:00 +0000</lastBuildDate><atom:link href="/tags/ffi/index.xml" rel="self" type="application/rss+xml"/><item><title>Lesson 10: Soundness — The ultimate safety guarantee</title><link>/post/rust/rust-unsafe-soundness/</link><pubDate>Fri, 04 Jul 2025 16:50:00 +0000</pubDate><guid>/post/rust/rust-unsafe-soundness/</guid><description>&lt;p&gt;A few months ago, someone filed a soundness bug against a crate I maintained. The report was elegant — three lines of safe code that triggered a use-after-free through my API. No &lt;code&gt;unsafe&lt;/code&gt; in the caller&amp;rsquo;s code. The bug was in my &lt;code&gt;unsafe&lt;/code&gt; implementation. I fixed it within the hour, cut a patch release, and filed a CVE advisory. That&amp;rsquo;s the social contract of soundness in Rust: if safe code can cause undefined behavior, the bug is &lt;em&gt;always&lt;/em&gt; in the library.&lt;/p&gt;</description></item><item><title>Lesson 9: napi-rs — Rust extensions for Node.js</title><link>/post/rust/rust-unsafe-ffi-node/</link><pubDate>Tue, 01 Jul 2025 13:26:00 +0000</pubDate><guid>/post/rust/rust-unsafe-ffi-node/</guid><description>&lt;p&gt;We had a Node.js microservice that validated JWTs. Under load, the &lt;code&gt;jsonwebtoken&lt;/code&gt; npm package was burning 40% of CPU on RSA signature verification. I wrote the verification in Rust with napi-rs, dropped it in as a replacement, and CPU usage fell to 8%. The JavaScript API didn&amp;rsquo;t change at all — same function name, same arguments, same return type. Just 5x faster.&lt;/p&gt;
&lt;p&gt;napi-rs is to Node.js what PyO3 is to Python. You write Rust, export it as a native Node addon, and call it from JavaScript like any other module. The framework handles all the N-API complexity, type marshaling, and async integration.&lt;/p&gt;</description></item><item><title>Lesson 8: PyO3 — Rust extensions for Python</title><link>/post/rust/rust-unsafe-ffi-python/</link><pubDate>Sat, 28 Jun 2025 08:14:00 +0000</pubDate><guid>/post/rust/rust-unsafe-ffi-python/</guid><description>&lt;p&gt;I had a Python service that processed 2 million JSON records daily. Profiling showed 80% of the time was spent in one function — a custom similarity scoring algorithm. I rewrote that single function in Rust with PyO3. Same API, same tests, same deployment. Processing time dropped from 47 minutes to 90 seconds. The Python team didn&amp;rsquo;t have to learn Rust, didn&amp;rsquo;t have to change their imports, didn&amp;rsquo;t even notice — they just saw their pipeline get 30x faster.&lt;/p&gt;</description></item><item><title>Lesson 7: Exposing Rust to C — cdylib and cbindgen</title><link>/post/rust/rust-unsafe-ffi-rust-from-c/</link><pubDate>Wed, 25 Jun 2025 15:40:00 +0000</pubDate><guid>/post/rust/rust-unsafe-ffi-rust-from-c/</guid><description>&lt;p&gt;A team I was advising had a massive C codebase — about 400,000 lines of networking code. They wanted to rewrite their TLS handling in Rust but couldn&amp;rsquo;t justify a full rewrite. The solution: build Rust as a shared library, expose a C-compatible API, and link it into the existing build. Took a week to get the first version working. The memory safety bugs in that module dropped to zero.&lt;/p&gt;</description></item><item><title>Lesson 6: FFI — Calling C from Rust</title><link>/post/rust/rust-unsafe-ffi-c/</link><pubDate>Mon, 23 Jun 2025 11:55:00 +0000</pubDate><guid>/post/rust/rust-unsafe-ffi-c/</guid><description>&lt;p&gt;My first real FFI project was binding to SQLite. I thought &amp;ldquo;how hard can it be — it&amp;rsquo;s just calling C functions.&amp;rdquo; Three days later I was debugging a segfault caused by a string lifetime issue where Rust freed a &lt;code&gt;CString&lt;/code&gt; while SQLite was still reading from the pointer. That experience taught me more about unsafe Rust than any tutorial ever could.&lt;/p&gt;
&lt;p&gt;Calling C from Rust is the most common FFI scenario. Every operating system API is C. Most high-performance libraries — OpenSSL, zlib, SQLite, libcurl — are C. If you&amp;rsquo;re writing systems software in Rust, you&amp;rsquo;ll need this skill.&lt;/p&gt;</description></item><item><title>Lesson 5: Building Safe Abstractions Over Unsafe Code — The encapsulation pattern</title><link>/post/rust/rust-unsafe-safe-abstractions/</link><pubDate>Fri, 20 Jun 2025 09:22:00 +0000</pubDate><guid>/post/rust/rust-unsafe-safe-abstractions/</guid><description>&lt;p&gt;The standard library&amp;rsquo;s &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt; contains over 50 &lt;code&gt;unsafe&lt;/code&gt; blocks. &lt;code&gt;HashMap&lt;/code&gt; has even more. Yet you use both every day without thinking about safety — because their public APIs are entirely safe. The &lt;code&gt;unsafe&lt;/code&gt; is invisible, encapsulated behind type system boundaries that make misuse impossible.&lt;/p&gt;
&lt;p&gt;This is the most important pattern in Rust: unsafe internals, safe surface. Master it, and you can build anything.&lt;/p&gt;
&lt;h2 id="the-core-principle"&gt;The Core Principle&lt;/h2&gt;
&lt;p&gt;An &lt;code&gt;unsafe&lt;/code&gt; block means &amp;ldquo;I&amp;rsquo;ve verified the invariants.&amp;rdquo; A safe API means &amp;ldquo;the type system prevents invariant violations.&amp;rdquo; The goal is to push all the verification into the implementation so that &lt;em&gt;users&lt;/em&gt; of your code can&amp;rsquo;t break the invariants no matter what they do.&lt;/p&gt;</description></item><item><title>Lesson 4: transmute — Type punning and its dangers</title><link>/post/rust/rust-unsafe-transmute/</link><pubDate>Wed, 18 Jun 2025 17:08:00 +0000</pubDate><guid>/post/rust/rust-unsafe-transmute/</guid><description>&lt;p&gt;I once watched a senior engineer &lt;code&gt;transmute&lt;/code&gt; a &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;/code&gt; into a &lt;code&gt;Vec&amp;lt;u32&amp;gt;&lt;/code&gt; and couldn&amp;rsquo;t figure out why it segfaulted on ARM but worked fine on x86. Spoiler: alignment. The allocator returned 1-byte-aligned memory for the &lt;code&gt;u8&lt;/code&gt; vec, and &lt;code&gt;u32&lt;/code&gt; needs 4-byte alignment. On x86 you pay a performance penalty; on ARM you get a bus error.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;transmute&lt;/code&gt; is Rust&amp;rsquo;s most powerful unsafe tool. It reinterprets the bits of one type as another type. No conversion, no transformation — just &amp;ldquo;these bytes are now a different type.&amp;rdquo; That power makes it incredibly useful and incredibly dangerous.&lt;/p&gt;</description></item><item><title>Lesson 3: Dereferencing Raw Pointers Safely — The patterns that work</title><link>/post/rust/rust-unsafe-deref/</link><pubDate>Mon, 16 Jun 2025 10:45:00 +0000</pubDate><guid>/post/rust/rust-unsafe-deref/</guid><description>&lt;p&gt;A colleague once showed me a bug that took them three days to find. Their &lt;code&gt;unsafe&lt;/code&gt; code dereferenced a pointer that was valid when created but dangling by the time it was used — a classic lifetime mismatch. The fix was two lines. The debugging was seventy-two hours. That ratio is why this lesson exists.&lt;/p&gt;
&lt;p&gt;Dereferencing raw pointers is the most common &lt;code&gt;unsafe&lt;/code&gt; operation you&amp;rsquo;ll encounter, and getting it right means following specific patterns. Not guidelines — patterns. Repeatable, auditable approaches that make your &lt;code&gt;unsafe&lt;/code&gt; code reviewable.&lt;/p&gt;</description></item><item><title>Lesson 2: Raw Pointers — *const T, *mut T and when you need them</title><link>/post/rust/rust-unsafe-raw-pointers/</link><pubDate>Sat, 14 Jun 2025 14:17:00 +0000</pubDate><guid>/post/rust/rust-unsafe-raw-pointers/</guid><description>&lt;p&gt;The first time I used raw pointers in Rust, I was porting a ring buffer from C. I&amp;rsquo;d written ring buffers in C a dozen times — head pointer, tail pointer, wrap around, done. In Rust, the borrow checker wanted nothing to do with my two mutable pointers into the same buffer. That&amp;rsquo;s when I learned what raw pointers are actually for.&lt;/p&gt;
&lt;h2 id="references-vs-raw-pointers"&gt;References vs Raw Pointers&lt;/h2&gt;
&lt;p&gt;Rust references (&lt;code&gt;&amp;amp;T&lt;/code&gt; and &lt;code&gt;&amp;amp;mut T&lt;/code&gt;) come with guarantees enforced by the compiler:&lt;/p&gt;</description></item><item><title>Lesson 1: What unsafe Actually Means — The contract you're signing</title><link>/post/rust/rust-unsafe-what-it-means/</link><pubDate>Thu, 12 Jun 2025 08:32:00 +0000</pubDate><guid>/post/rust/rust-unsafe-what-it-means/</guid><description>&lt;p&gt;I spent my first six months writing Rust thinking &lt;code&gt;unsafe&lt;/code&gt; meant &amp;ldquo;this code is dangerous and you should feel bad.&amp;rdquo; That misunderstanding cost me weeks — I&amp;rsquo;d bend over backwards to avoid it, writing convoluted safe wrappers around problems that genuinely needed a raw pointer or two. Once I actually read the Rustonomicon and understood what &lt;code&gt;unsafe&lt;/code&gt; &lt;em&gt;really&lt;/em&gt; means, everything clicked.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s clear this up properly.&lt;/p&gt;
&lt;h2 id="unsafe-is-not-what-you-think"&gt;unsafe Is Not What You Think&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s the biggest misconception in the Rust ecosystem: &lt;code&gt;unsafe&lt;/code&gt; does not mean &amp;ldquo;this code is broken&amp;rdquo; or &amp;ldquo;this code does bad things.&amp;rdquo; It means &lt;strong&gt;&amp;ldquo;I, the programmer, am upholding invariants that the compiler cannot verify.&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>