简体   繁体   中英

Trying to dynamically load module with Dynlink

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

It looks like I was not on the ball with my search engine skills in this case.

Some more digging turned up an archived email chain that states that the referenced module ( Plug in this case) must have been completely evaluated before the dynamically loaded module can call into it.

The solution is to separate the code that loads the extension module and the code that the extension module calls into two separate modules (so now there will be three modules in total).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM