Has anyone tried to embed the OCaml bytecode compiler in C?
What was your experience?
Is this so difficult that I shouldn’t bother?
Has anyone tried to embed the OCaml bytecode compiler in C?
What was your experience?
Is this so difficult that I shouldn’t bother?
I think this is just a matter of embedding the OCaml toplevel.
Hi,
something like this might work,
I haven’t tested this exact code,
I’m pasting it from a bigger project:
caml.ml:
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:
#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:
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.