Skip to content

Commit 7dbf060

Browse files
committed
chore(cbind): swap cbind for ffi (nim-ffi part 9)
1 parent 596510e commit 7dbf060

38 files changed

Lines changed: 1166 additions & 7204 deletions

.github/copilot-instructions.md

Lines changed: 29 additions & 18 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,38 @@ 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 top-level FFI module: `declareLibrary` + `{.ffi.}` /
466+
`{.ffiCtor.}` / `{.ffiDtor.}` / `{.ffiEvent.}` annotations and the ported
467+
libp2p logic; `genBindings()` emits the bindings.
468+
- `libp2p/config.nim`config types and parsing, `include`d into `libp2p.nim`.
469+
- `c_bindings/`generated C header (`libp2p.h`), consumed by
470+
`logos-co/logos-libp2p-module`.
471+
- `cddl_bindings/` — generated CDDL schema for the CBOR wire format.
468472

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

476481
**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
482+
- Requests/responses are CBOR; declare `{.ffi.}` object types for them — never
483+
raw `ptr`/`pointer` across the boundary.
484+
- Stream handles are plain `uint64` ids tracked in `LibP2P` state (nim-ffi has
485+
no handle type for incoming streams).
486+
- Convert config-parsing failures to `return err(...)`; never `raiseAssert` on
487+
host-supplied input (the constructor returns a `Result`).
488+
- Protocol/pubsub handlers are `{.ffiEvent.}` — host code subscribes via the
489+
generated `libp2p_add_event_listener`.
479490

480491
---
481492

@@ -489,9 +500,9 @@ nimble examples # Build and run C examples
489500
| `daily_ci_report.yml` | Daily CI failure reporting: opens/updates GitHub issues for failed daily CI runs |
490501
| `daily_nimbus.yml` | Nimbus-specific test matrix |
491502
| `daily_runnable_examples.yml` | Daily runnable examples checks |
492-
| `cbindings.yml` | C bindings compilation and tests |
503+
| `cbindings.yml` | FFI library build + C/CDDL binding generation |
493504
| `coverage.yml` | Code coverage (uploads to codecov) |
494-
| `linters.yml` | nph formatting checks |
505+
| `linters.yml` | nph (Nim) + clang-format (cbind C/H) formatting checks |
495506
| `pr_lint.yml` | PR title/description linting |
496507
| `auto_assign_pr.yml` | Automatically assigns reviewers to PRs |
497508
| `update_copilot_instructions.yml` | Weekly automated update of copilot-instructions.md |

.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

.github/workflows/mobile_android.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,16 @@ jobs:
5959
test -f "$out/include/nim_ffi_prelude.h"
6060
test -f "$out/include/tinycbor/cbor.h"
6161
test -f "$out/include/cddl_bindings/libp2p.cddl"
62-
test -x "$out/bin/libp2p_ffi_android_check"
62+
test -x "$out/bin/libp2p_android_check"
6363
6464
readelf -h "$out/lib/liblibp2p.so" | tee liblibp2p.readelf
65-
readelf -h "$out/bin/libp2p_ffi_android_check" | tee check.readelf
65+
readelf -h "$out/bin/libp2p_android_check" | tee check.readelf
6666
6767
grep -q "Machine:[[:space:]]*${{ matrix.machine }}" liblibp2p.readelf
6868
grep -q "Machine:[[:space:]]*${{ matrix.machine }}" check.readelf
6969
7070
file "$out/lib/liblibp2p.so"
71-
file "$out/bin/libp2p_ffi_android_check"
71+
file "$out/bin/libp2p_android_check"
7272
7373
- name: Enable KVM for Android emulator
7474
if: matrix.abi == 'x86_64'
@@ -93,7 +93,7 @@ jobs:
9393
adb shell "mkdir -p /data/local/tmp/nim-libp2p"
9494
adb push "result-x86_64/lib/liblibp2p.so" "/data/local/tmp/nim-libp2p/"
9595
adb push "result-x86_64/lib/libc++_shared.so" "/data/local/tmp/nim-libp2p/"
96-
adb push "result-x86_64/bin/libp2p_ffi_android_check" "/data/local/tmp/nim-libp2p/"
97-
adb shell "chmod 755 /data/local/tmp/nim-libp2p/libp2p_ffi_android_check"
98-
adb shell "cd /data/local/tmp/nim-libp2p && LD_LIBRARY_PATH=/data/local/tmp/nim-libp2p ./libp2p_ffi_android_check; echo RC=\$?" | tee run.log
96+
adb push "result-x86_64/bin/libp2p_android_check" "/data/local/tmp/nim-libp2p/"
97+
adb shell "chmod 755 /data/local/tmp/nim-libp2p/libp2p_android_check"
98+
adb shell "cd /data/local/tmp/nim-libp2p && LD_LIBRARY_PATH=/data/local/tmp/nim-libp2p ./libp2p_android_check; echo RC=\$?" | tee run.log
9999
grep -q '^RC=0' run.log

.github/workflows/mobile_ios.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,10 @@ jobs:
7171
test -f "$out/include/nim_ffi_prelude.h"
7272
test -f "$out/include/tinycbor/cbor.h"
7373
test -f "$out/include/cddl_bindings/libp2p.cddl"
74-
test -x "$out/bin/libp2p_ffi_ios_check"
74+
test -x "$out/bin/libp2p_ios_check"
7575
7676
otool -l "$out/lib/liblibp2p.dylib" | tee liblibp2p.otool
77-
otool -l "$out/bin/libp2p_ffi_ios_check" | tee check.otool
77+
otool -l "$out/bin/libp2p_ios_check" | tee check.otool
7878
lipo -info "$out/lib/liblibp2p.dylib" | tee liblibp2p.lipo
7979
lipo -info "$out/lib/liblibp2p.a" | tee liblibp2p_static.lipo
8080
@@ -84,4 +84,4 @@ jobs:
8484
grep -q "arm64" liblibp2p_static.lipo
8585
8686
file "$out/lib/liblibp2p.dylib"
87-
file "$out/bin/libp2p_ffi_ios_check"
87+
file "$out/bin/libp2p_ios_check"

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)