# Embedding the OCaml bytecode compiler in C

**URL:** <https://discuss.ocaml.org/t/embedding-the-ocaml-bytecode-compiler-in-c/16814>\
**Category:** Learning\
**Tags:** embedding\
**Created:** [June 14, 2025, 2:16pm UTC](https://discuss.ocaml.org/t/embedding-the-ocaml-bytecode-compiler-in-c/16814 "2025-06-14T14:16:09Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![joelreymont](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/joelreymont/32/5937_2.png) [@joelreymont](https://discuss.ocaml.org/u/joelreymont)\
**Post date:** [June 14, 2025, 2:16pm UTC](https://discuss.ocaml.org/t/embedding-the-ocaml-bytecode-compiler-in-c/16814/1 "2025-06-14T14:16:09Z")

</div>

Has anyone tried to embed the OCaml bytecode compiler in C?

What was your experience?

Is this so difficult that I shouldn’t bother?

---

<div class="post-metadata">

**Author:** ![joelreymont](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/joelreymont/32/5937_2.png) [@joelreymont](https://discuss.ocaml.org/u/joelreymont)\
**Post date:** [June 14, 2025, 7:52pm UTC](https://discuss.ocaml.org/t/embedding-the-ocaml-bytecode-compiler-in-c/16814/2 "2025-06-14T19:52:08Z")

</div>

I think this is _just_ a matter of embedding the OCaml toplevel.

---

<div class="post-metadata">

**Author:** ![progutils](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/progutils/32/5918_2.png) [@progutils](https://discuss.ocaml.org/u/progutils)\
**Post date:** [June 15, 2025, 8:54pm UTC](https://discuss.ocaml.org/t/embedding-the-ocaml-bytecode-compiler-in-c/16814/3 "2025-06-15T20:54:35Z")

</div>

Hi,

something like this might work,  
I haven’t tested this exact code,  
I’m pasting it from a bigger project:

caml.ml:

```auto
let _OUTSZ = 1024 * 500
let outbuf = ref (Buffer.create 0)
let run_caml phrase =
  let () = Buffer.clear !outbuf in
  let errbuf = Buffer.create 2048 in
  let ppf = Format.formatter_of_buffer errbuf in
  let input = Toploop.String phrase in
  let old_warning_formatter = !Location.formatter_for_warnings in
  let new_formatter = Format.formatter_of_buffer errbuf in
  let () = Location.formatter_for_warnings := new_formatter in
  let () =
    try
      if Toploop.prepare ppf ~input:input () then begin
          if Toploop.run_script ppf input [||] then begin
              let () = Format.pp_print_flush new_formatter () in
              let () = Location.formatter_for_warnings := old_warning_formatter in
              flush_all ()
            end;
        end;
    with
    | Compenv.Exit_with_status status ->
       Format.pp_print_flush Format.err_formatter () in

  if 0 < Buffer.length errbuf then
    let contents = Buffer.contents errbuf in
    let () = print_endline contents in
    contents
  else
    Buffer.contents !outbuf

let _ = Callback.register "run_caml" run_caml

let wout str =
  let bytes = Bytes.of_string str in
  let addlen = Bytes.length bytes in
  let () = if _OUTSZ < (Buffer.length !outbuf) + addlen then failwith "output buffer full" in
  Buffer.add_bytes !outbuf bytes

```

caml.c:

```auto
#include <caml/alloc.h>
#include <caml/callback.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>

#define BUFSZ 1024 * 500

void run_caml(const char *phrase,
              char *out) {
    static bool started = false;
    if (!started) {
        char_os *args = NULL;
        caml_startup(&args);
        started = true;
        printf("%d OCaml startup complete\n", getpid());
        fflush(stdout);
    }

    CAMLparam0();
    CAMLlocal2(caml_phrase, res);
    caml_phrase = caml_copy_string(phrase);
    res = caml_callback(
        *caml_named_value("run_caml"),
        caml_phrase);
    memset(out, 0, BUFSZ);
    mlsize_t len = caml_string_length(res);
    if (0 < len) {
        memcpy(out, Bytes_val(res), len <= BUFSZ ? len : BUFSZ);
    }
}

```

build.sh:

```auto
ocamlc -custom -output-obj -o caml_byte.o \
-I +compiler-libs \
compilerlibs/ocamlcommon.cma \
compilerlibs/ocamlbytecomp.cma \
compilerlibs/ocamltoplevel.cma \
caml.ml

cc -c -o caml.o -I lib/ocaml src/caml.c
cp ocaml/runtime/libcamlrun_pic.a libcamlrun.a
ar r libcamlrun.a caml.o caml_byte.o

```

If you get `Error: Unbound module` errors, make a directory,  
for example `ocamllibs` and set the environment variable `OCAMLLIB` to it:  
`setenv("OCAMLLIB", "ocamllibs", 1);`, and then copy necessary \*.cmi files into it.

---

<div class="post-metadata">

**Author:** ![joelreymont](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/joelreymont/32/5937_2.png) [@joelreymont](https://discuss.ocaml.org/u/joelreymont)\
**Post date:** [June 16, 2025, 10:55am UTC](https://discuss.ocaml.org/t/embedding-the-ocaml-bytecode-compiler-in-c/16814/4 "2025-06-16T10:55:47Z")

</div>

Thank you! I’ll post an update once I try it.
