|
| 1 | +The wrapper crate and C/C++ Headers in this folder are auto-generated from the Rust-Lightning |
| 2 | +source by the c-bindings-gen crate contained in the source tree and |
| 3 | +[cbindgen](https://github.com/eqrion/cbindgen). They are intended to be used as a base for building |
| 4 | +language-specific bindings, and are thus incredibly low-level and may be difficult to work with |
| 5 | +directly. |
| 6 | + |
| 7 | +In other words, if you're reading this, you're either writing bindings for a new language, or |
| 8 | +you're in the wrong place - individual language bindings should come with their own documentation. |
| 9 | + |
| 10 | +LDK C Bindings |
| 11 | +=================== |
| 12 | + |
| 13 | +The C bindings available at include/lightning.h require inclusion of include/rust_types.h first. |
| 14 | + |
| 15 | +All of the Rust-Lightning types are mapped into C equivalents which take a few forms, namely: |
| 16 | + |
| 17 | + * Structs are mapped into a simple wrapper containing a pointer to the native Rust-Lightning |
| 18 | + object and a flag to indicate whether the object is owned or only a reference. Such mappings |
| 19 | + usually generate a `X_free` function which must be called to release the allocated resources. |
| 20 | + Note that calling `X_free` will do nothing if the underlying pointer is NULL or if the reference |
| 21 | + flag is set. |
| 22 | + |
| 23 | + You MUST NOT create such wrapper structs manually, relying instead on constructors which have |
| 24 | + been mapped from equivalent Rust constructors. |
| 25 | + |
| 26 | + Note that, thanks to the is-reference flag, such structs effectively represent both `&RustThing` |
| 27 | + and `RustThing`. Further, the same applies to `Option<RustThing>`, in which cases `inner` may be |
| 28 | + set to NULL. |
| 29 | + |
| 30 | + For example, this is the mapping of ChannelManager. |
| 31 | + ``` |
| 32 | + typedef struct MUST_USE_STRUCT LDKChannelManager { |
| 33 | + /** ... */ |
| 34 | + LDKlnChannelManager *inner; |
| 35 | + bool _underlying_ref; |
| 36 | + } LDKChannelManager; |
| 37 | + ``` |
| 38 | + |
| 39 | + * Traits are mapped into a concrete struct containing a void pointer and a jump table listing the |
| 40 | + functions which the trait must implement. The void pointer may be set to any value and is never |
| 41 | + interpreted (or dereferenced) by the bindings logic in any way. It is passed as the first |
| 42 | + argument to all function calls in the trait. You may wish to use it as a pointer to your own |
| 43 | + internal data structure, though it may also occasionally make sense to e.g. cast a file |
| 44 | + descriptor into a void pointer and use it to track a socket. |
| 45 | + |
| 46 | + Each trait additionally contains a `free` and `clone` function pointer, which may be NULL. The |
| 47 | + `free` function is passed the void pointer when the object is `Drop`ed in Rust. The `clone` |
| 48 | + function is passed the void pointer when the object is `Clone`ed in Rust, returning a new void |
| 49 | + pointer for the new object. |
| 50 | + |
| 51 | + For example, `LDKSocketDescriptor` is mapped as follows: |
| 52 | + ``` |
| 53 | + typedef struct LDKSocketDescriptor { |
| 54 | + void *this_arg; |
| 55 | + /** ... */ |
| 56 | + uintptr_t (*send_data)(void *this_arg, LDKu8slice data, bool resume_read); |
| 57 | + /** ... */ |
| 58 | + void (*disconnect_socket)(void *this_arg); |
| 59 | + bool (*eq)(const void *this_arg, const void *other_arg); |
| 60 | + uint64_t (*hash)(const void *this_arg); |
| 61 | + void *(*clone)(const void *this_arg); |
| 62 | + void (*free)(void *this_arg); |
| 63 | + } LDKSocketDescriptor; |
| 64 | + ``` |
| 65 | + |
| 66 | + * Rust structs that implement a trait result in the generation of an `X_as_Y` function which allows |
| 67 | + you to use the native Rust object in place of the trait. Such generated objects are only valid as |
| 68 | + long as the original Rust native object is owned by a C-wrapped struct, and has not been `free`'d |
| 69 | + or moved as a part of a Rust function call. |
| 70 | + |
| 71 | + * Rust "unitary" enums are mapped simply as an equivalent C enum, however some Rust enums have |
| 72 | + variants which contain payloads. Such enums are mapped automatically by cbindgen as a tag which |
| 73 | + indicates the type and a union which holds the relevant fields for a given tag. A `X_free` |
| 74 | + function is provided for the enum as a whole which automatically frees the correct fields for a |
| 75 | + given tag, and a `Sentinel` tag is provided which causes the free function to do nothing (but |
| 76 | + which must never appear in an enum when accessed by Rust code). The `Sentinel` tag is used by |
| 77 | + the C++ wrapper classes to allow moving the ownership of an enum while invalidating the old copy. |
| 78 | + |
| 79 | + * Struct member functions are mapped as `Struct_function_name` and take a reference to the mapped |
| 80 | + struct as their first argument. Free-standing functions are mapped simply as `function_name` and |
| 81 | + take the relevant mapped type arguments. |
| 82 | + |
| 83 | + Functions may return a reference to an underlying Rust object with a mapped struct or an owned |
| 84 | + Rust object with the same. The mapped struct contains a flag to indicate if the poitned-to Rust |
| 85 | + object is owned or only a reference, and the object's corresponding free function will Do The |
| 86 | + Right Thing based on the flag. In order to determine the expected return type, you should |
| 87 | + reference the Rust documentation for the function. |
| 88 | + |
| 89 | + Similarly, when a function takes an `Option<RustType>` as a parameter or a return value, the C |
| 90 | + type is the same as if it took only `RustType`, with the `inner` field set to NULL to indicate |
| 91 | + None. For example, `ChannelManager_create_channel` takes an `Option<LDKUserCOnfig>` not an |
| 92 | + `LDKUserConfig`, but its definition is: |
| 93 | + ``` |
| 94 | + MUST_USE_RES LDKCResult_NoneAPIErrorZ ChannelManager_create_channel(const LDKChannelManager *this_arg, ..., LDKUserConfig override_config); |
| 95 | + ``` |
| 96 | + |
| 97 | +As the bindings are auto-generated, the best resource for documentation on them is the native Rust |
| 98 | +docs available via `cargo doc` or [docs.rs/lightning](https://docs.rs/lightning). |
| 99 | + |
| 100 | +The memory model is largely the Rust memory model and not a native C-like memory model. Thus, |
| 101 | +function parameters are largely only ever passed by reference or by move, with pass-by-copy |
| 102 | +semantics only applying to primitive types. However, because the underlying types are largely |
| 103 | +pointers, the same function signature may imply two different memory ownership semantics. Thus, you |
| 104 | +MUST read the Rust documentation while using the C bindings. For functions which ownership is moved |
| 105 | +to Rust, the corresponding `X_fre`e function MUST NOT be called on the object, whereas for all other |
| 106 | +objects, `X_free` MUST be used to free resources. |
| 107 | + |
| 108 | +LDK C++ Bindings |
| 109 | +================ |
| 110 | + |
| 111 | +The C++ bindings available at include/lightningpp.hpp require extern "C" inclusion of lightning.h |
| 112 | +and rust_types.h first. They represent thin wrappers around the C types which provide a few |
| 113 | +C++-isms to make memory model correctness easier to achieve. They provide: |
| 114 | + * automated destructors which call the relevant `X_free` C functions, |
| 115 | + * move constructors both from C++ classes and the original C struct, with the original object |
| 116 | + cleared to ensure destruction/`X_free` calls do not cause a double-free. |
| 117 | + * Move semantics via the () operator, returning the original C struct and clearing the C++ object. |
| 118 | + This allows calls such as `C_function(cpp_object)` which works as expected with move semantics. |
| 119 | + |
| 120 | +In general, you should prefer to use the C++ bindings if possible, as they make memory leaks and |
| 121 | +other violations somewhat easier to avoid. Note that, because the C functions are not redefined in |
| 122 | +C++, all functions return the C type. Thus, you must bind returned values to the equivalent C++ type |
| 123 | +(replacing LDKX with LDK::X) to ensure the destructor is properly run. A demonstration of such usage |
| 124 | +is available at [demo.cpp](demo.cpp). |
| 125 | + |
| 126 | +**It is highly recommended that you test any code which relies on the C (or C++) bindings in |
| 127 | +valgrind, MemorySanitizer, or other similar tools to ensure correctness.** |
| 128 | + |
0 commit comments