Skip to content

Commit 110a621

Browse files
committed
chore(cbind): swap cbind for ffi (nim-ffi part 9)
1 parent ffaed94 commit 110a621

25 files changed

Lines changed: 1130 additions & 7170 deletions

.github/copilot-instructions.md

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ nim-libp2p/
4141
│ ├── integration/ # Integration tests (WebSocket, AutoTLS, peer ID auth)
4242
│ └── interop/ # Cross-implementation interoperability tests
4343
├── examples/ # Tutorial and example applications
44-
├── cbind/ # C/FFI bindings layer
44+
├── cbind/ # C/CDDL FFI bindings (generated via nim-ffi)
4545
├── docs/ # Documentation
4646
│ ├── README.md # Documentation index
4747
│ ├── development.md # Setup and testing guide
@@ -206,7 +206,8 @@ These flags are used in CI and tests:
206206

207207
### Memory Management
208208
- Memory model: `--mm:refc` (reference counting)
209-
- For C bindings (`cbind/`): use `createShared`/`freeShared` for cross-thread objects
209+
- For C bindings (`cbind/`): the FFI runtime (threads, request channel, shared
210+
memory, CBOR codec) is provided by `nim-ffi`; annotate procs/types instead
210211

211212
### Style
212213

@@ -454,28 +455,37 @@ These flags are used in CI and tests:
454455

455456
---
456457

457-
## C Bindings (`cbind/`)
458+
## C/CDDL Bindings (`cbind/`)
458459

459-
The `cbind/` directory contains the C/FFI layer for using nim-libp2p from C/C++:
460+
The `cbind/` directory exposes nim-libp2p to C via the [`nim-ffi`](https://github.com/logos-messaging/nim-ffi)
461+
framework. nim-ffi provides the worker thread, request channel, shared memory,
462+
CBOR codec and event queue, and *generates* the C/CDDL bindings from the
463+
annotations in `libp2p.nim`:
460464

461-
- `libp2p.nim` — FFI function implementations (exported with `{.exportc.}`)
462-
- `libp2p.h` — Generated C header
463-
- `ffi_types.nim` — C-compatible type definitions
464-
- `types.nim` — Additional C-compatible type implementations
465-
- `alloc.nim` — Cross-thread memory allocation helpers
466-
- `libp2p_thread/` — Thread management for async operations from C
467-
- `examples/cbindings.c`, `examples/echo.c` — C usage examples
465+
- `libp2p.nim` — the only source file: `declareLibrary` + `{.ffi.}` /
466+
`{.ffiCtor.}` / `{.ffiDtor.}` / `{.ffiEvent.}` annotations and the ported
467+
libp2p logic; `genBindings()` emits the bindings.
468+
- `c_bindings/` — generated C header (`libp2p.h`), consumed by
469+
`logos-co/logos-libp2p-module`.
470+
- `cddl_bindings/` — generated CDDL schema for the CBOR wire format.
468471

469472
```sh
470473
cd cbind
471-
nimble libDynamic # Build .so/.dylib/.dll
472-
nimble libStatic # Build .a
473-
nimble examples # Build and run C examples
474+
nimble setup
475+
nimble buildffi # Build ../build/liblibp2p.{so,dylib,dll}
476+
nimble genbindings_c # Generate c_bindings/libp2p.h
477+
nimble genbindings_cddl # Generate the CDDL schema
474478
```
475479

476480
**cbind conventions**:
477-
- Validate all `cstring` pointer parameters for `nil` before use; call the callback with `RET_ERR` if nil
478-
- Use `valueOr` (not `tryGet()`) when converting cstring multiaddresses to `MultiAddress` objects
481+
- Requests/responses are CBOR; declare `{.ffi.}` object types for them — never
482+
raw `ptr`/`pointer` across the boundary.
483+
- Stream handles are plain `uint64` ids tracked in `LibP2P` state (nim-ffi has
484+
no handle type for incoming streams).
485+
- Convert config-parsing failures to `return err(...)`; never `raiseAssert` on
486+
host-supplied input (the constructor returns a `Result`).
487+
- Protocol/pubsub handlers are `{.ffiEvent.}` — host code subscribes via the
488+
generated `libp2p_add_event_listener`.
479489

480490
---
481491

@@ -489,7 +499,7 @@ nimble examples # Build and run C examples
489499
| `daily_ci_report.yml` | Daily CI failure reporting: opens/updates GitHub issues for failed daily CI runs |
490500
| `daily_nimbus.yml` | Nimbus-specific test matrix |
491501
| `daily_runnable_examples.yml` | Daily runnable examples checks |
492-
| `cbindings.yml` | C bindings compilation and tests |
502+
| `cbindings.yml` | FFI library build + C/CDDL binding generation |
493503
| `coverage.yml` | Code coverage (uploads to codecov) |
494504
| `linters.yml` | nph formatting checks |
495505
| `pr_lint.yml` | PR title/description linting |

.github/workflows/cbindings.yml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: C bindings examples
1+
name: C bindings
22

33
on:
44
push:
@@ -54,7 +54,7 @@ jobs:
5454
run: |
5555
nimble install_pinned
5656
57-
- name: Build and run c bindings examples
57+
- name: Build FFI library and generate C/CDDL bindings
5858
run: |
5959
nim --version
6060
nimble --version
@@ -64,18 +64,18 @@ jobs:
6464
cd cbind
6565
nimble install_pinned
6666
nimble setup
67+
nimble buildffi
68+
nimble genbindings_c
69+
nimble genbindings_cddl
70+
71+
- name: Build and run C bindings examples
72+
run: |
73+
cd cbind
6774
nimble examples
6875
69-
# Temporary parallel job: builds the new nim-ffi library (cbind/libp2p_ffi.nim)
70-
# and generates its C/CDDL bindings. Folded into the main flow at the flip PR,
71-
# when libp2p_ffi.nim replaces the legacy libp2p.nim.
72-
#
73-
# Disabled until the final PR of the nim-ffi migration series: libp2p_ffi.nim is
74-
# built up incrementally across PRs 2..9 and only compiles end-to-end at the
75-
# flip. Re-enable (drop `if: false`) once the library is complete and expected
76-
# to pass.
76+
# macOS coverage for the FFI library build + C/CDDL binding generation; the
77+
# main c-bindings job above covers linux.
7778
c-bindings-ffi:
78-
if: false
7979
timeout-minutes: 30
8080
strategy:
8181
fail-fast: false

cbind/.clang-format

Lines changed: 0 additions & 5 deletions
This file was deleted.

cbind/alloc.nim

Lines changed: 0 additions & 145 deletions
This file was deleted.

cbind/cbind.nimble

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mode = ScriptMode.Verbose
33
packageName = "cbind"
44
version = "0.1.0"
55
author = "Status Research & Development GmbH"
6-
description = "C bindings for LibP2P implementation"
6+
description = "C bindings for nim-libp2p, generated via nim-ffi"
77
license = "MIT"
88

99
import os, strutils, sequtils
@@ -21,43 +21,6 @@ task install_pinned,
2121
let deps = readFile(".pinned").splitWhitespace().mapIt(it.split(";", 1)[1])
2222
exec "nimble install -y " & deps.join(" ")
2323

24-
proc getLibExt(libType: string): string =
25-
if libType == "static":
26-
"a"
27-
else:
28-
when defined(windows):
29-
"dll"
30-
elif defined(macosx):
31-
"dylib"
32-
else:
33-
"so"
34-
35-
proc buildCBindings(libType: string, params = "") =
36-
let buildDir = "../build"
37-
38-
if not dirExists buildDir:
39-
mkDir buildDir
40-
41-
var extra_params = params
42-
for i in 2 ..< paramCount():
43-
extra_params &= " " & paramStr(i)
44-
45-
let ext = getLibExt(libType)
46-
let app = if libType == "static": "staticlib" else: "lib"
47-
48-
exec "nim c --out:" & buildDir & "/libp2p." & ext & " --threads:on --app:" & app &
49-
" --opt:size --noMain --mm:refc --header -d:metrics" &
50-
" --nimMainPrefix:libp2p --nimcache:nimcache libp2p.nim"
51-
52-
task libDynamic, "Generate dynamic bindings":
53-
buildCBindings "dynamic", ""
54-
55-
task libStatic, "Generate static bindings":
56-
buildCBindings "static", ""
57-
58-
# nim-ffi library, built in parallel to the legacy cbind above (see libp2p_ffi.nim).
59-
# Renamed over libp2p.nim at the flip PR, which drops everything above this line.
60-
6124
proc findInstalledPkgDir(prefix: string): string =
6225
## Path of an installed dep dir matching `prefix` (e.g. "ffi-"). install_pinned
6326
## drops cbind's pinned deps under the project-local `nimbledeps/pkgs2`; a plain
@@ -108,16 +71,16 @@ proc buildFfiLib() =
10871
exec "nim c --out:" & buildDir & "/liblibp2p." & ffiLibExt() &
10972
" --threads:on --app:lib --opt:size --noMain --mm:refc -d:metrics" &
11073
" -d:ffiThreadExitTimeoutMs=5000" & ffiDepPaths() &
111-
" --nimMainPrefix:liblibp2p --nimcache:nimcache libp2p_ffi.nim"
74+
" --nimMainPrefix:liblibp2p --nimcache:nimcache libp2p.nim"
11275

11376
task buildffi, "Build the FFI shared library":
11477
buildFfiLib()
11578

11679
proc genBindingsFor(lang, outDir: string) =
11780
exec "nim c --threads:on --app:lib --noMain --mm:refc -d:metrics" &
11881
" --nimMainPrefix:liblibp2p -d:ffiGenBindings -d:targetLang=" & lang &
119-
" -d:ffiOutputDir=" & outDir & " -d:ffiSrcPath=libp2p_ffi.nim" & ffiDepPaths() &
120-
" --nimcache:nimcache_" & lang & " -o:/dev/null libp2p_ffi.nim"
82+
" -d:ffiOutputDir=" & outDir & " -d:ffiSrcPath=libp2p.nim" & ffiDepPaths() &
83+
" --nimcache:nimcache_" & lang & " -o:/dev/null libp2p.nim"
12184

12285
task genbindings_c, "Generate C bindings (cbind/c_bindings)":
12386
genBindingsFor("c", "c_bindings")

0 commit comments

Comments
 (0)