diff options
author | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-07-28 00:10:00 +1000 |
---|---|---|
committer | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-07-28 00:10:00 +1000 |
commit | 7b86e3251a28406862fe16d49f8533beb8ca3150 (patch) | |
tree | a90166418ada7ad88500843ce8881a453c1d4721 | |
parent | 6b004c5ac6a25f1020774276803b62e8619ea61e (diff) |
start on ocaml bindings
-rw-r--r-- | bindgen/ocaml/bin/dune | 4 | ||||
-rw-r--r-- | bindgen/ocaml/bin/main.ml | 1 | ||||
-rw-r--r-- | bindgen/ocaml/bindings/bindings_sys.ml | 49 | ||||
-rw-r--r-- | bindgen/ocaml/bindings/caml_bindings.c | 132 | ||||
-rw-r--r-- | bindgen/ocaml/bindings/celeritas.h | 21 | ||||
-rw-r--r-- | bindgen/ocaml/bindings/dune | 13 | ||||
-rw-r--r-- | bindgen/ocaml/celeritas.opam | 31 | ||||
-rw-r--r-- | bindgen/ocaml/dune-project | 26 | ||||
-rw-r--r-- | bindgen/ocaml/lib/dune | 2 | ||||
-rw-r--r-- | bindgen/ocaml/lib/lib.ml | 0 | ||||
-rw-r--r-- | bindgen/ocaml/lib/maths.ml | 42 | ||||
-rw-r--r-- | bindgen/ocaml/test/dune | 2 | ||||
-rw-r--r-- | bindgen/ocaml/test/test_celeritas.ml | 0 |
13 files changed, 323 insertions, 0 deletions
diff --git a/bindgen/ocaml/bin/dune b/bindgen/ocaml/bin/dune new file mode 100644 index 0000000..fd2576a --- /dev/null +++ b/bindgen/ocaml/bin/dune @@ -0,0 +1,4 @@ +(executable + (public_name celeritas) + (name main) + (libraries celeritas)) diff --git a/bindgen/ocaml/bin/main.ml b/bindgen/ocaml/bin/main.ml new file mode 100644 index 0000000..7bf6048 --- /dev/null +++ b/bindgen/ocaml/bin/main.ml @@ -0,0 +1 @@ +let () = print_endline "Hello, World!" diff --git a/bindgen/ocaml/bindings/bindings_sys.ml b/bindgen/ocaml/bindings/bindings_sys.ml new file mode 100644 index 0000000..1c100e9 --- /dev/null +++ b/bindgen/ocaml/bindings/bindings_sys.ml @@ -0,0 +1,49 @@ +(* automatically generated by ocaml-bindgen 0.0.1 *) + +type lifetime = + | Function + (** The value can live for the lifetime of the function call, which upon return will signal that the + value can be dropped (finalizer?) *) + | Ocaml (** The value is managed by the OCaml runtime *) + | C + (** The value is allocated and passed to C which is then in charge of cleaning it up *) + +type 'a cptr = { lifetime : lifetime; addr : nativeint } + +external bindgen_alloc : size:int -> nativeint = "bindgen_alloc" +external bindgen_free : nativeint -> unit = "bindgen_free" +external bindgen_alloc_string : string -> nativeint = "bindgen_alloc_string" + +let sizeof _ = 4 (* TODO: how to handle different types? *) + +let create_ptr (value : 'a) : 'a cptr = + let addr = bindgen_alloc ~size:(sizeof value) in + print_endline ("Addr: " ^ Nativeint.to_string addr); + Gc.finalise bindgen_free addr; + { lifetime = Ocaml; addr } + +let make_cstr (s: string) : char cptr = + let addr = bindgen_alloc_string s in + { lifetime = Ocaml; addr } + +type nonrec core +type nonrec glfwwindow +external get_global_core : unit -> core cptr = "caml_get_global_core" +external core_Bringup : + optional_window:unit cptr -> unit = "caml_core_Bringup" +external frame_Begin : unit -> unit = "caml_frame_Begin" +external frame_Draw : unit -> unit = "caml_frame_Draw" +external frame_End : unit -> unit = "caml_frame_End" +type nonrec vec2 = { + x: float ; + y: float } +type nonrec vec3 = { + x: float ; + y: float ; + z: float } +type nonrec vec4 = { + x: float ; + y: float ; + z: float ; + w: float } +external vec3_add : b:vec3 -> a:vec3 -> vec3 = "caml_vec3_add" diff --git a/bindgen/ocaml/bindings/caml_bindings.c b/bindgen/ocaml/bindings/caml_bindings.c new file mode 100644 index 0000000..4a7dc70 --- /dev/null +++ b/bindgen/ocaml/bindings/caml_bindings.c @@ -0,0 +1,132 @@ +/* automatically generated by ocaml-bindgen 0.0.1 */ + +#include "celeritas.h" +#include <caml/alloc.h> +#include <caml/callback.h> +#include <caml/fail.h> +#include <caml/memory.h> +#include <caml/mlvalues.h> +#include <caml/unixsupport.h> +Core* caml_get_global_core() { + CAMLparam0(); + CAMLlocal1(result); + result = get_global_core(); + CAMLreturn(result); +} + +void caml_core_Bringup(value caml_optional_window) { + CAMLparam1(caml_optional_window); + void* optional_window = Nativeint_val(Field(caml_optional_window, 1)); + core_Bringup(optional_window); + CAMLreturn0; +} + +void caml_frame_Begin() { + CAMLparam0(); + frame_Begin(); + CAMLreturn0; +} + +void caml_frame_Draw() { + CAMLparam0(); + frame_Draw(); + CAMLreturn0; +} + +void caml_frame_End() { + CAMLparam0(); + frame_End(); + CAMLreturn0; +} + +Vec2* caml_Vec2_of_value(value caml_x) { + Vec2* x = malloc(sizeof(struct Vec2)); + x->x = Double_val(Field(caml_x, 0)); + x->y = Double_val(Field(caml_x, 1)); + return x; +} + +value caml_Vec2_to_value(struct Vec2* x) { + CAMLparam0(); + CAMLlocal1(caml_x); + caml_x = caml_alloc_tuple(2); + Store_field(caml_x, 0, caml_copy_double(x->x)); + Store_field(caml_x, 1, caml_copy_double(x->y)); + CAMLreturn(caml_x); +} + +Vec3* caml_Vec3_of_value(value caml_x) { + Vec3* x = malloc(sizeof(struct Vec3)); + x->x = Double_val(Field(caml_x, 0)); + x->y = Double_val(Field(caml_x, 1)); + x->z = Double_val(Field(caml_x, 2)); + return x; +} + +value caml_Vec3_to_value(struct Vec3* x) { + CAMLparam0(); + CAMLlocal1(caml_x); + caml_x = caml_alloc_tuple(3); + Store_field(caml_x, 0, caml_copy_double(x->x)); + Store_field(caml_x, 1, caml_copy_double(x->y)); + Store_field(caml_x, 2, caml_copy_double(x->z)); + CAMLreturn(caml_x); +} + +Vec4* caml_Vec4_of_value(value caml_x) { + Vec4* x = malloc(sizeof(struct Vec4)); + x->x = Double_val(Field(caml_x, 0)); + x->y = Double_val(Field(caml_x, 1)); + x->z = Double_val(Field(caml_x, 2)); + x->w = Double_val(Field(caml_x, 3)); + return x; +} + +value caml_Vec4_to_value(struct Vec4* x) { + CAMLparam0(); + CAMLlocal1(caml_x); + caml_x = caml_alloc_tuple(4); + Store_field(caml_x, 0, caml_copy_double(x->x)); + Store_field(caml_x, 1, caml_copy_double(x->y)); + Store_field(caml_x, 2, caml_copy_double(x->z)); + Store_field(caml_x, 3, caml_copy_double(x->w)); + CAMLreturn(caml_x); +} + +Vec3 caml_vec3_add(value caml_a, value caml_b) { + CAMLparam2(caml_a, caml_b); + CAMLlocal1(result); + Vec3 a = caml_Vec3_of_value(caml_a); + Vec3 b = caml_Vec3_of_value(caml_b); + result = vec3_add(a, b); + CAMLreturn(result); +} + + +#include <stdlib.h> +value bindgen_alloc(value caml_size) { + CAMLparam1(caml_size); + + // Convert OCaml integer to C size + size_t size = Int_val(caml_size); + printf("Allocated size %ld \n", size); + + void* ptr = malloc(sizeof(size)); + if (ptr == NULL) { + // TODO: handle allocation failure + CAMLreturn(Val_unit); + } + + // Wrap the pointer as an OCaml value + CAMLreturn(caml_copy_nativeint(ptr)); +} + +void bindgen_free(value caml_addr) { + free(Nativeint_val(caml_addr)); +} + +value bindgen_alloc_string(value caml_string) { + CAMLparam1(caml_string); + char* str = String_val(caml_string); + CAMLreturn(caml_copy_nativeint((intnat)str)); +} diff --git a/bindgen/ocaml/bindings/celeritas.h b/bindgen/ocaml/bindings/celeritas.h new file mode 100644 index 0000000..fce4d62 --- /dev/null +++ b/bindgen/ocaml/bindings/celeritas.h @@ -0,0 +1,21 @@ +/* The Goal of this file is to test ocaml-bindgen on it to start moving development over into OCaml */ + +// #include <stdbool.h> +// #include <stdint.h> + +typedef struct Core Core; +typedef struct GLFWwindow GLFWwindow; + +Core* get_global_core(); +void core_Bringup(void* optional_window); + +void frame_Begin(); +void frame_Draw(); +void frame_End(); + + +struct Vec2 { float x; float y; }; +typedef struct Vec3 { float x; float y; float z; } Vec3; +struct Vec4 { float x; float y; float z; float w; }; + +Vec3 vec3_add(Vec3 a, Vec3 b);
\ No newline at end of file diff --git a/bindgen/ocaml/bindings/dune b/bindgen/ocaml/bindings/dune new file mode 100644 index 0000000..673491d --- /dev/null +++ b/bindgen/ocaml/bindings/dune @@ -0,0 +1,13 @@ +(library + (name bindings) + (libraries bindgen)) + +(rule + (alias gen_bindings) + (deps celeritas.h) + (targets bindings_sys.ml caml_bindings.c) + (action + (run + %{bin:ocaml-bindgen} celeritas.h bindings) + ) + (mode (promote (until-clean))))
\ No newline at end of file diff --git a/bindgen/ocaml/celeritas.opam b/bindgen/ocaml/celeritas.opam new file mode 100644 index 0000000..bd5c0c8 --- /dev/null +++ b/bindgen/ocaml/celeritas.opam @@ -0,0 +1,31 @@ +# This file is generated by dune, edit dune-project instead +opam-version: "2.0" +synopsis: "A short synopsis" +description: "A longer description" +maintainer: ["Maintainer Name"] +authors: ["Author Name"] +license: "LICENSE" +tags: ["topics" "to describe" "your" "project"] +homepage: "https://github.com/username/reponame" +doc: "https://url/to/documentation" +bug-reports: "https://github.com/username/reponame/issues" +depends: [ + "ocaml" + "dune" {>= "3.14"} + "odoc" {with-doc} +] +build: [ + ["dune" "subst"] {dev} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] +] +dev-repo: "git+https://github.com/username/reponame.git" diff --git a/bindgen/ocaml/dune-project b/bindgen/ocaml/dune-project new file mode 100644 index 0000000..3f94e1d --- /dev/null +++ b/bindgen/ocaml/dune-project @@ -0,0 +1,26 @@ +(lang dune 3.14) + +(name celeritas) + +(generate_opam_files true) + +(source + (github username/reponame)) + +(authors "Author Name") + +(maintainers "Maintainer Name") + +(license LICENSE) + +(documentation https://url/to/documentation) + +(package + (name celeritas) + (synopsis "A short synopsis") + (description "A longer description") + (depends ocaml dune) + (tags + (topics "to describe" your project))) + +; See the complete stanza docs at https://dune.readthedocs.io/en/stable/dune-files.html#dune-project diff --git a/bindgen/ocaml/lib/dune b/bindgen/ocaml/lib/dune new file mode 100644 index 0000000..6803cec --- /dev/null +++ b/bindgen/ocaml/lib/dune @@ -0,0 +1,2 @@ +(library + (name celeritas)) diff --git a/bindgen/ocaml/lib/lib.ml b/bindgen/ocaml/lib/lib.ml new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/bindgen/ocaml/lib/lib.ml diff --git a/bindgen/ocaml/lib/maths.ml b/bindgen/ocaml/lib/maths.ml new file mode 100644 index 0000000..8810f48 --- /dev/null +++ b/bindgen/ocaml/lib/maths.ml @@ -0,0 +1,42 @@ +(** Maths and linear algebra. + Ideally we should avoid doing large amounts of math computation in OCaml, + and so exposing more functionality for batch processing via Core is preferred *) + +(** Base functions that a 2D Vector must support *) +module type Vector = sig + type t + + val add : t -> t -> t + val sub : t -> t -> t + val scalar_mul : float -> t -> t + val dot : t -> t -> float +end + +(** Functor that takes a module implementing the Vector signature and returns + a module that implements most vector space operations *) +module VectorSpace (V : Vector) = struct + include V + + let scalar_div s v = scalar_mul (1. /. s) v + let neg v = scalar_mul (-1.0) v + let length_squared v = dot v v + let length v = sqrt (dot v v) + let magnitude = length + + let normalize v = + let len = length v in + if len > 0.0 then scalar_mul (1.0 /. len) v else v + + let distance u v = sub u v |> length +end + +module Vec3Float = struct + type t = { x : float; y : float; z : float } + + let add u v = { x = u.x +. v.x; y = u.y +. v.y; z = u.z +. v.z } + let sub u v = { x = u.x -. v.x; y = u.y -. v.y; z = u.z -. v.z } + let scalar_mul k v = { x = k *. v.x; y = k *. v.y; z = k *. v.z } + let dot u v = (u.x *. v.x) +. (u.y *. v.y) +. (u.z *. v.z) +end + +module Vec3 = VectorSpace (Vec3Float)
\ No newline at end of file diff --git a/bindgen/ocaml/test/dune b/bindgen/ocaml/test/dune new file mode 100644 index 0000000..bf9e4e1 --- /dev/null +++ b/bindgen/ocaml/test/dune @@ -0,0 +1,2 @@ +(test + (name test_celeritas)) diff --git a/bindgen/ocaml/test/test_celeritas.ml b/bindgen/ocaml/test/test_celeritas.ml new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/bindgen/ocaml/test/test_celeritas.ml |