Claude Code Plugins

Community-maintained marketplace

Feedback
0
0

|

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name clojure-coffi
description Coffi FFI library for calling native C code from Clojure via Panama FFM API (JDK 22+). Use when: wrapping native C libraries, calling native functions, working with off-heap memory and arenas, etc.

Coffi FFI Library

Coffi wraps the Panama Foreign Function & Memory API for calling native C code from Clojure.

Setup

Add to deps.edn:

;; use gh cli to check latest commit with `gh browse  -c -n IGJoshua/coffi`
io.github.IGJoshua/coffi                  {:git/sha "ae3e38a449c88b998db98b0d4bffa9908dea1c79"}

JVM argument required:

--enable-native-access=ALL-UNNAMED

Or in deps.edn alias:

{:aliases {:dev {:jvm-opts ["--enable-native-access=ALL-UNNAMED"]}}}

Prep deps

clojure -Xdeps prep :aliases '[:dev :test]'

Quick Start

(require '[coffi.ffi :as ffi :refer [defcfn]]
         '[coffi.mem :as mem])

;; Wrap a native function
(defcfn strlen
  strlen [::mem/c-string] ::mem/long)

(strlen "hello") ;; => 5

;; Load a library
(ffi/load-system-library "z")        ;; System library
(ffi/load-library "path/to/lib.so")  ;; From path

Core Pattern: defcfn

(defcfn var-name
  "docstring"
  native_symbol_name [arg-types...] return-type)

;; With wrapper logic
(defcfn var-name
  "native_symbol" [arg-types...] return-type
  native-fn        ;; Binds the raw native function
  [clj-args...]    ;; Clojure argument list
  (body...))       ;; Wrapper body that calls native-fn

Type Quick Reference

Coffi Type C Type Notes
::mem/byte int8_t
::mem/short int16_t
::mem/int int32_t
::mem/long int64_t
::mem/float float
::mem/double double
::mem/pointer void*
::mem/c-string char* Null-terminated
::mem/void void Return only
[::mem/struct [...]] struct See below
[::mem/array type n] type[n] Fixed size
[::ffi/fn [args] ret] function ptr Callbacks

For complete type reference: references/types.md

Struct Definition

(require '[coffi.layout :as layout])

;; Always use layout/with-c-layout for FFI structs
(mem/defalias ::my-struct
  (layout/with-c-layout
    [::mem/struct
     [[:name ::mem/c-string]
      [:count ::mem/int]
      [:value ::mem/double]]]))

;; Use in function
(defcfn process-data
  process_data [::my-struct] ::mem/int)

(process-data {:name "test" :count 5 :value 3.14})

Memory Arenas

Always use confined-arena with with-open for temporary allocations:

(with-open [arena (mem/confined-arena)]
  (let [ptr (mem/serialize data type arena)]
    (native-fn ptr)))
;; Memory freed automatically

Arena types:

  • confined-arena - Thread-local, freed on close (most common)
  • shared-arena - Multi-thread, freed on close
  • auto-arena - GC-managed
  • global-arena - Never freed

For details: references/memory.md

Common Patterns

Output pointer parameter

(defcfn open-resource
  "open_resource" [::mem/c-string ::mem/pointer] ::mem/int
  native-open
  [name]
  (with-open [arena (mem/confined-arena)]
    (let [out-ptr (mem/alloc-instance ::mem/pointer arena)
          code (native-open name out-ptr)]
      (if (zero? code)
        (mem/deserialize-from out-ptr ::mem/pointer)
        (throw (ex-info "Failed" {:code code}))))))

String with explicit length

(defcfn bind-text
  "bind_text" [::mem/pointer ::mem/c-string ::mem/int] ::mem/int
  native-bind
  [handle text]
  (let [bytes (.getBytes text "UTF-8")]
    (native-bind handle text (count bytes))))

Array serialization

;; Serialize array
(mem/serialize [1 2 3 4] [::mem/array ::mem/int 4] arena)

;; For raw Java arrays (better performance)
(mem/serialize (int-array [1 2 3 4]) [::mem/array ::mem/int 4 :raw? true] arena)

Callback to native code

(defcfn set-callback
  set_callback [[::ffi/fn [::mem/int] ::mem/int]] ::mem/void)

(set-callback (fn [x] (* x 2)))

For more examples: references/examples.md

Reference Files

Read these references depending on what you are doing. You should read at least one of the now, if not all of them

  • types.md - Complete type system (primitives, structs, arrays, enums, unions, custom types)
  • memory.md - Memory management (arenas, allocation, serialization, pointer ops)
  • examples.md - Real-world patterns from sqlite4clj and coffi tests