Sunday 29 November 2009

Dynlink for native code

Today I've spent a lot of time trying to understand how Dynlink works.

I started with the following code:

main.ml:

let hello str =
print_string str ;
print_newline ()

let _ = hello "Main"

let _ =
try
Dynlink.loadfile "test.cmxs"
with Dynlink.Error(e) -> print_string (Dynlink.error_message e)

let _ = print_newline ()

main.mli:

val hello : string -> unit

test.ml

let _ = Main.hello "Test"

and then compiled everything the following way:

$ ocamlc main.mli
$ ocamlfind ocamlopt -package dynlink -linkpkg -o main main.ml
$ ocamlopt -shared -o test.cmxs test.ml

As I result I've got executable file:

$ file main
main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped

and plugin:

$ file test.cmxs
test.cmxs: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, not stripped

Unfortunately, this does not work:

$ ./main
Main
no implementation available for Main

I've spent a couple of hours trying to play with Dynlink and compiler options but failed to achieve any result until I found the following thread in fa.caml newsgroup where Xavier Leroy answers the question about exactly the same problem:

“The issue here is that when Dynlink.loadfile is called, module [...] is not yet completely evaluated, therefore it is not yet visible to dynamically-loaded code. The solution is just to split your main program in two modules [...]”

So I've created mainly.ml:

let hello str =
print_string str ;
print_newline ()

and mainly.mli:

val hello : string -> unit

Then modified main.ml:

let _ = Mainly.hello "Main"

let _ =
try
Dynlink.loadfile "test.cmxs"
with Dynlink.Error(e) -> print_string (Dynlink.error_message e)

let _ = print_newline ()

and test.ml:

let _ = Mainly.hello "test"

Compilation is similar:

$ ocamlc mainly.mli
$ ocamlfind ocamlopt -package dynlink -linkpkg -o main mainly.ml main.ml
$ ocamlopt -shared -o test.cmxs test.ml

And now it works!

$ ./main
Main
Test

So I'm happy.

Disclaimer

I just started to [seriously] study OCaml. So I know about it close to nothing.