There is an easy workaround: Don't put the external declaration into the mli, just a val. When installing the library, take care to also include the cmx file. This way, the extra function wrapper can be eliminated by the automatic inliner of ocamlopt. Of course, this works only for native code. Gerd Am Freitag, den 27.12.2013, 13:27 +0000 schrieb David Allsopp: > I've hit an unexpected gotcha using external declarations in .mli files. > > I have a module where the functions exported are all C stubs and so, knowing > that exposing the external definition in the .mli file allows the compiler > to generate more efficient function calls, I'd exported the functions using > external declarations in the .mli files. > > The module also contains an important piece of initialisation code which > must be run before any of the other functions will work. So, simplified, it > looks like this: > > Foo.ml > ------ > external bar : 'a -> unit = "my_c_implementation_of_bar" > external baz : unit -> unit = "very_important_initialisation_stub" > > let _ = > baz () > > Foo.mli > ------- > external bar : 'a -> unit = "my_c_implementation_of_bar" > > This is then wrapped up in a .cmxa file and the .cmxa, .cmx, .a and .cmi > files installed as normal. Now I produce a program using it: > > Bar.ml > ------ > Foo.bar 42 > > and compile this program using ocamlopt -o fubar foo.cmxa Bar.ml > > When I run it, the initialisation code in Foo.ml calling baz never takes > place (which I can tell because it means that the call to Foo.bar, which > does take place, fails). > > After much head-scratching, I realised that the reason for this is that the > external declaration in Foo.mli means that the module Foo presumably isn't > linked as its code was deemed unnecessary (as it would be if Bar.ml only > referenced types in the module Foo, rather than values). > > So, my question: is that really correct behaviour? I can see why referencing > a type only is not sufficient to cause a module to be linked, but surely > referencing a value (even when it's declared external) should not exempt the > linker from actually linking the module code - at least when the module > contains top-level code (rather than just static values or functions)? > > It seems a shame to slow the calls down (however trivially) by removing the > external declarations from the .mli file (i.e. declaring val bar : 'a -> > unit in the .mli) simply to keep the linker happy. > > > David > > PS I don't expect it's relevant, but for this I was running OCaml 4.01.0 on > Linux/armv6l > > -- ------------------------------------------------------------ Gerd Stolpmann, Darmstadt, Germany gerd@gerd-stolpmann.de My OCaml site: http://www.camlcity.org Contact details: http://www.camlcity.org/contact.html Company homepage: http://www.gerd-stolpmann.de ------------------------------------------------------------