I am trying to achieve something similar to eval()
in OCaml.
I have a string
and I want to get an OCaml function out of it.
Currently I am doing the following:
I dump the string to new.ml
and compile the file:
Compile.implementation Format.std_formatter "new.ml" "New"
Then I try to dynlink
the file:
Dynlink.loadfile "new.cmo";
But if I try to do New.foo
it fails. I am not sure why I cannot access the module New after Dynlink
ing. Am I missing something?
Thanks!
The comment of Dynlink.loadfile
says:
No facilities are provided to access value names defined by the unit. Therefore, the unit must register itself its entry points with the main program, e.g. by modifying tables of functions.
The loader program cannot access values of dyn-loaded module without any hint, since it has no idea what values are defined in it just from the .cmo
file. The dynamic loaded module must register its entry point to some state defined in the loader program.
Here is such a minimal example. First, the module for the entry points:
(* entry.ml *)
let f : (unit -> unit) ref = ref (fun () -> assert false)
The loader program:
(* loader.ml *)
let () =
Dynlink.loadfile "plugin.cmo";
!Entry.f ()
The plugin to be dyn-loaded:
(* plugin.ml *)
let () = Entry.f := (fun () -> prerr_endline "hello world")
Here, Plugin
registers its function to Entry.f
which is statically linked to Loader
, so that Loader
can access the function.
They must be compiled as follows:
$ ocamlc -o loader.exe dynlink.cma entry.ml loader.ml
$ ocamlc -c plugin.ml
Execution of loader.exe
should demonstrate how the dyn loading works:
$ ./loader.exe
hello world
Note that Entry
and Loader
must be different modules. Otherwise, you get Uninitialized_global
exception at dyn-loading Plugin
. Dyn-loaded modules can only access values in "already initialized modules", and the loader module thinks itself not yet initialized when Dynlink.loadfile
is called, since the entire evaluation of the module is not finished yet.
Entry.f
is the simplest state to have only one entry point. To dyn-load many values, you may want to have more complicated data structure, such as (string, (unit -> unit)) list ref
or (string, (unit -> unit)) Hashtbl.t
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With