Interaction with environments that conforms to a C-like ABI.
This namespace is mainly about defining C structures in order to pass them or to understand them when interacting with native functions. It could be when using JNI on the JVM or when calling WebAssembly functions in Clojurescript, for instance.
This opens the road to interacting with languages like C++ and Rust since they allow for defining such C structures and commonly do so in the context of libraries.
BinF already provides utilities for handling arbitrary data in native memory or in WebAssembly memory.
For example, on the JVM, DirectByteBuffer
implements view protocols and is commonly used with JNI.
Some WebAssembly runtimes such as Wasmer
use them to represent the memory of a WebAssembly module. In
JS, WebAssembly memories are buffers from which a view can be built.
What is missing is knowing how to use a C-like ABI which relies on following some rules. For instance, the members of a structure are aligned on specific memory addresses for performance reasons. This namespace provides utilities for defining such composite data structures as EDN and computing everything there is to compute for following those ABI rules.
3 definitions are needed for understanding these utilities:
An env
is a map containing information needed for computing those rules such as the alignment being used.
See env
for creating one.
A description map describes either a primitive type (eg. u32
) or a composite data structure (eg. struct
).
A description function takes an env
and produces a description map.
A description map is plain data containing eveything that is needed for handling this type. For instance, a description of a structure contains computed memory offsets of all its data fields.
This namespace contains ready description functions for primitive types (such as f32
) as well as functions
for creating description functions for composite ones (such as array
or struct
).
See struct
for a small example and a full one in the helins.binf.example.cabi
namespace from the repository.
Source code also clearly shows what is being outputed. While daunting at first, this namespace is actually quite simple.
Interaction with environments that conforms to a C-like ABI. This namespace is mainly about defining C structures in order to pass them or to understand them when interacting with native functions. It could be when using JNI on the JVM or when calling WebAssembly functions in Clojurescript, for instance. This opens the road to interacting with languages like C++ and Rust since they allow for defining such C structures and commonly do so in the context of libraries. BinF already provides utilities for handling arbitrary data in native memory or in WebAssembly memory. For example, on the JVM, `DirectByteBuffer` implements view protocols and is commonly used with JNI. Some WebAssembly runtimes such as `Wasmer` use them to represent the memory of a WebAssembly module. In JS, WebAssembly memories are buffers from which a view can be built. What is missing is knowing how to use a C-like ABI which relies on following some rules. For instance, the members of a structure are aligned on specific memory addresses for performance reasons. This namespace provides utilities for defining such composite data structures as EDN and computing everything there is to compute for following those ABI rules. 3 definitions are needed for understanding these utilities: - An `env` is a map containing information needed for computing those rules such as the alignment being used. See [[env]] for creating one. - A description map describes either a primitive type (eg. [[u32]]) or a composite data structure (eg. [[struct]]). - A description function takes an `env` and produces a description map. A description map is plain data containing eveything that is needed for handling this type. For instance, a description of a structure contains computed memory offsets of all its data fields. This namespace contains ready description functions for primitive types (such as [[f32]]) as well as functions for creating description functions for composite ones (such as [[array]] or [[struct]]). See [[struct]] for a small example and a full one in the `helins.binf.example.cabi` namespace from the repository. Source code also clearly shows what is being outputed. While daunting at first, this namespace is actually quite simple.
(aligned align offset)
Re-align offset
given align
(an alignment in bytes).
Used by utilities in this namespace.
(aligned 8
13)
;; 13 is re-aligned to 16, a multiple of 8
Re-align `offset` given `align` (an alignment in bytes). Used by utilities in this namespace. ```clojure (aligned 8 13) ;; 13 is re-aligned to 16, a multiple of 8 ```
(array description-fn n-element)
Given a description function for a type and a number of elements, returns a description function for an array.
Given a description function for a type and a number of elements, returns a description function for an array.
(bool _env)
Given an env
, returns a map describing a boolean.
Given an `env`, returns a map describing a boolean.
(enum type constant+)
Given a type name and a sequence of constants, returns a description function for an enum named as such and composed of those constants.
A constant is either an identifier (string or keyword) or a vector [identifier value]
.
It looks exactly like defining an enum in C in that regard.
Attention, enums are brittle from an ABI point of view and should be discouraged. For instance, the Google Fuchsia projects even explicitely bans them.
(def make-enum
(enum :MyEnum
[:a
:b
[:c 42]
:d]))
Given a type name and a sequence of constants, returns a description function for an enum named as such and composed of those constants. A constant is either an identifier (string or keyword) or a vector `[identifier value]`. It looks exactly like defining an enum in C in that regard. Attention, enums are brittle from an ABI point of view and should be discouraged. For instance, the Google Fuchsia projects even explicitely bans them. ```clojure (def make-enum (enum :MyEnum [:a :b [:c 42] :d])) ```
(env n-byte-word)
Creates a minimal env
map which describes the used alignment and the size of a pointer. Those
informations are necessary for computing about any C type.
This function leverages the fact that in modern architectures, alignment matches the size of pointers (eg. on 64-bit machine, alignment is 8 bytes and a pointer is 8 bytes as well).
Creates a minimal `env` map which describes the used alignment and the size of a pointer. Those informations are necessary for computing about any C type. This function leverages the fact that in modern architectures, alignment matches the size of pointers (eg. on 64-bit machine, alignment is 8 bytes and a pointer is 8 bytes as well).
(f32 env)
Given an env
, returns a map describing a 32-bit floating value.
Given an `env`, returns a map describing a 32-bit floating value.
(f64 env)
Given an env
, returns a map describing a 64-bit floating value.
Given an `env`, returns a map describing a 64-bit floating value.
(force-align f align)
Sometimes, different alignments are used at the same time. For instance, an inner structure might have a different alignment than its outer structure. This function alters a description function in order to force a particular alignment.
;; Forcing 4 byte alignment on the inner struct
(struct :OuterStruct
[:a f32]
[:b (force-align (struct :InnerStruct
[:inner-a i64])
4)])
Sometimes, different alignments are used at the same time. For instance, an inner structure might have a different alignment than its outer structure. This function alters a description function in order to force a particular alignment. ```clojure ;; Forcing 4 byte alignment on the inner struct (struct :OuterStruct [:a f32] [:b (force-align (struct :InnerStruct [:inner-a i64]) 4)]) ```
(force-env f env)
Akin to force-align
but forces the given env
over the one being used rather than merely the alignment.
Akin to [[force-align]] but forces the given `env` over the one being used rather than merely the alignment.
(i16 env)
Given an env
, returns a map describing a signed 16-bit integer.
Given an `env`, returns a map describing a signed 16-bit integer.
(i32 env)
Given an env
, returns a map describing a signed 32-bit integer.
Given an `env`, returns a map describing a signed 32-bit integer.
(i64 env)
Given an env
, returns a map describing a signed 64-bit integer.
Given an `env`, returns a map describing a signed 64-bit integer.
(i8 _env)
Given an env
, returns a map describing a signed 8-bit integer.
Given an `env`, returns a map describing a signed 8-bit integer.
(name-set member name)
Assoc'es a new name to a description map.
See name-get
.
Assoc'es a new name to a description map. See [[name-get]].
(ptr type)
Given a description function for a type, returns a function taking an env
and returning
a map describing a pointer for that type.
Given a description function for a type, returns a function taking an `env` and returning a map describing a pointer for that type.
(struct type member+)
Given a type name and a sequence of members, returns a description function for a structure named as such and composed of those members.
A member is a vector [member-name description-function]
.
The following example creates a structure containing a byte and an array of doubles. The resulting description function is then being passed an environment map were words are 8 bytes (ie. 64-bit machine).
That description is plain data and contains computed offsets of all members.
(def make-struct
(struct :MyStruct
[[:a u8]
[:b (array f64
10)]]))
(def my-struct-map
(make-struct (env 8)))
Given a type name and a sequence of members, returns a description function for a structure named as such and composed of those members. A member is a vector `[member-name description-function]`. The following example creates a structure containing a byte and an array of doubles. The resulting description function is then being passed an environment map were words are 8 bytes (ie. 64-bit machine). That description is plain data and contains computed offsets of all members. ```clojure (def make-struct (struct :MyStruct [[:a u8] [:b (array f64 10)]])) (def my-struct-map (make-struct (env 8))) ```
(u16 env)
Given an env
, returns a map describing an unsigned 16-bit integer.
Given an `env`, returns a map describing an unsigned 16-bit integer.
(u32 env)
Given an env
, returns a map describing an unsigned 32-bit integer.
Given an `env`, returns a map describing an unsigned 32-bit integer.
(u64 env)
Given an env
, returns a map describing an unsigned 64-bit integer.
Given an `env`, returns a map describing an unsigned 64-bit integer.
(u8 _env)
Given an env
, returns a map describing an unsigned 8-bit integer.
Given an `env`, returns a map describing an unsigned 8-bit integer.
(union type member+)
Given a type name and a sequence of members, returns a description function for a union named as such and composed of those members.
A member is a vector [member-name description-function]
.
Behaves similarly to struct
.
Given a type name and a sequence of members, returns a description function for a union named as such and composed of those members. A member is a vector `[member-name description-function]`. Behaves similarly to [[struct]].
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close