I'm trying to set up dynamic loading of OCaml modules using Dynlink. I wrote a very simple test program, but it's not working.
This test program consists of two modules, Plug and Ext. Plug is the "main" module. It knows the filename of Ext and loads it with Dynlink.loadfile. Ext references Plug, and calls a function in Plug that informs Plug about one of its functions so that it can be called. After Plug loads Ext, it calls the function that Ext is supposed to have registered.
The Ext module loads successfully if I write it so that it doesn't execute any code. However, if I include the part that registers its extension function with Plug, then I get an error: The module 'Plug' is not yet initialized.
I don't understand how Plug could not be initialized yet, since it is already executing. (Actually I don't know what it means for an OCaml module to be initialized.)
I've reduced the code down to pretty much the least necessary to reproduce the problem. I am using OCaml 4.01.0 on Linux.
Here's the main module:
(* plug.ml *)
type xfn = string -> unit
let dummy_func str =
print_endline ("Dummy: " ^ str)
let ext_func : xfn ref = ref dummy_func
let register func =
ext_func := func
let call () =
(!ext_func) "calling"
(* load extension *)
let () =
try
print_endline "Loading ext.";
Dynlink.loadfile "ext.cmo";
print_endline "Loaded ext.";
()
with
| Dynlink.Error e ->
print_endline (Dynlink.error_message e);
print_endline "Calling registered func.";
call ()
This is the extension file:
(* ext.ml *)
open Plug
let myext str =
print_endline ("Ext: " ^ str)
let () = Plug.register myext
I used this shell script to compile the executable:
#!/bin/sh
ocamlc -c plug.ml && \
ocamlc -c ext.ml && \
ocamlc -o plug dynlink.cma plug.cmo ext.cmo \
|| exit 1
This is the output I get:
Loading ext.
error while linking ext.cmo.
The module `Plug' is not yet initialized
Calling registered func.
Dummy: calling