Objects and Dynlink

I have a system which uses Dynlink to dynamically load some code (.cmxs). The problem that I am having is that you cannot use the Object system in OCaml with Dynlink when naively compiling (I haven’t tried bytecode). I feel that I am missing some compiler option when compiling the code or I am misunderstanding how to use Dynlink. The error is below:

error loading shared library: obj_test.cmxs: undefined symbol: camlCamlinternalOO__create_object_opt_1533

Is this a known issue when using Dynlink? Thank you very much for any help/ideas/suggestions that you may have.

A minimal example which shows the behavior is below:

obj_test.ml

class istack = object
    val mutable v = [0; 2]

    method pop =
      match v with
      | hd :: tl ->
          v <- tl;
          Some hd
      | [] -> None

    method push hd =
      v <- hd :: v
  end

which is complied thus: ocamlfind opt -shared -o obj_test.cmxs obj_test.ml

main.ml

let load_test_plugin fname =
  let fname =  Dynlink.adapt_filename fname in
  try
    Dynlink.loadfile fname
  with
  | (Dynlink.Error err) as e ->
     print_endline ("ERROR loading plugin: " ^ (Dynlink.error_message err));
     raise e

let _ =
  load_test_plugin Sys.argv.(1)

which is compiled thus: ocamlfind opt -package dynlink -linkpkg main.ml

When you try to run the code: ./a.out obj_test.cmxs, you will get the error indicated above.

1 Like

The problem is that the main program is not linked with the internal
values needed to handle object-based constructs (namely the
CamlinternalOO module whose name appears as the prefix of the
undefined symbol).

A simple, yet unsatisfactory, workaround is to add this line to your
main file: let _ = object end, as it will force the link with the missing
module.

However, I think the problem deserves a bug report.

1 Like

Thank you for the information and workaround! I will file a bug report on mantis.

Related issue: I am trying to use cohttp-lwt-unix in a Dynlink plugin but I am getting the following error:

ERROR loading plugin: no implementation available for CamlinternalBigarray
Fatal error: exception Dynlink.Error(_)

@xclerc do you happen to have a workaround for this issue as well? :slight_smile:

It’s basically the same. The mantis bug has a discussion. Basically, we need to use “-linkall” when compiling. I am working on that at the moment :slight_smile:

1 Like

Sure; let _ = Bigarray.Genarray.create should do the same for bigarrays as let _ = object end does for objets.

I recommend to put the “-linkall” link-time option when building an executable that is going to dynamically load stuff through the Dynlink interface, This way, all the definitions visible to the executable will be made available to the dynamically-loaded code.

Without “-linkall”, the OCaml static linker will delete the definitions that are not used – unless you add dummy uses for those definitions, as suggested in the previous replies, but it gets tiring after a while.

2 Likes

Indeed, the problem I am having with “-linkall” is that the linker is denying that modules exist even though they are installed and ocamlfind can find the packages. I will be able to look at this again but not right this moment. Thank you for your help!

-linkall works on my side, thanks!