<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE message PUBLIC
  "-//MLarc//DTD MLarc output files//EN"
  "../../mlarc.dtd"[
  <!ATTLIST message
    listname CDATA #REQUIRED
    title CDATA #REQUIRED
  >
]>

  <?xml-stylesheet href="../../mlarc.xsl" type="text/xsl"?>


<message 
  url="2009/01/7d3913d17469c862ee3e5ff3fceb4c1b"
  from="Ben Jakb &lt;ben.jakb@g...&gt;"
  author="Ben Jakb"
  date="2009-01-10T15:28:28"
  subject="Re: [Caml-list] Shared libraries with ocamlopt callable from C (without main())?"
  prev="2009/01/f244a598c38ac31f2efdb5190bcc1764"
  next="2009/01/d52308de08216f29d09caa52b2f05dcf"
  prev-in-thread="2009/01/9cb3439eed351c14973ea021f31f2a83"
  next-in-thread="2009/01/d52308de08216f29d09caa52b2f05dcf"
  prev-thread="2009/01/91c2e13999073da72a0efffe4acd71e6"
  next-thread="2009/01/2112b46e78c48d5a1e210bbd83ebb31a"
  root="../../"
  period="month"
  listname="caml-list"
  title="Archives of the Caml mailing list">

<thread subject="Shared libraries with ocamlopt callable from C (without main())?">
<msg 
  url="2009/01/5c289b2a10ec7c701b7b196284e19c78"
  from="Ben Aurel &lt;ben.aurel@g...&gt;"
  author="Ben Aurel"
  date="2009-01-08T22:46:53"
  subject="Shared libraries with ocamlopt callable from C (without main())?">
<msg 
  url="2009/01/7143e848af5c993fe0de325d727426b6"
  from="Matthieu Dubuget &lt;matthieu.dubuget@g...&gt;"
  author="Matthieu Dubuget"
  date="2009-01-09T08:21:47"
  subject="Re: [Caml-list] Shared libraries with ocamlopt callable from C (without main())?">
<msg 
  url="2009/01/c2641b2a52606a6aff3aabe0204177b0"
  from="RABIH.ELCHAAR@s..."
  author="RABIH.ELCHAAR@s..."
  date="2009-01-09T08:47:02"
  subject="RE: [Caml-list] Shared libraries with ocamlopt callable from C(without main())?">
</msg>
<msg 
  url="2009/01/eabe0f1126a9d8c37e11c08054d99a36"
  from="Ben Jakb &lt;ben.jakb@g...&gt;"
  author="Ben Jakb"
  date="2009-01-10T01:22:05"
  subject="Re: [Caml-list] Shared libraries with ocamlopt callable from C (without main())?">
<msg 
  url="2009/01/9cb3439eed351c14973ea021f31f2a83"
  from="Matthieu Dubuget &lt;matthieu.dubuget@g...&gt;"
  author="Matthieu Dubuget"
  date="2009-01-10T11:50:49"
  subject="Re: [Caml-list] Shared libraries with ocamlopt callable from C (without main())?">
<msg 
  url="2009/01/7d3913d17469c862ee3e5ff3fceb4c1b"
  from="Ben Jakb &lt;ben.jakb@g...&gt;"
  author="Ben Jakb"
  date="2009-01-10T15:28:28"
  subject="Re: [Caml-list] Shared libraries with ocamlopt callable from C (without main())?">
<msg 
  url="2009/01/d52308de08216f29d09caa52b2f05dcf"
  from="Matthieu Dubuget &lt;matthieu.dubuget@g...&gt;"
  author="Matthieu Dubuget"
  date="2009-01-10T15:36:44"
  subject="Re: [Caml-list] Shared libraries with ocamlopt callable from C (without main())?">
<msg 
  url="2009/01/7504deae4c49192ff0d96985d8da8c12"
  from="Ben Jakb &lt;ben.jakb@g...&gt;"
  author="Ben Jakb"
  date="2009-01-10T18:08:40"
  subject="Re: [Caml-list] Shared libraries with ocamlopt callable from C (without main())?">
</msg>
</msg>
</msg>
<msg 
  url="2009/01/9b0dd581f47b1eb4890a146553820492"
  from="Ben Jakb &lt;ben.jakb@g...&gt;"
  author="Ben Jakb"
  date="2009-01-10T18:18:05"
  subject="Re: Shared libraries with ocamlopt callable from C (without main())?">
</msg>
</msg>
<msg 
  url="2009/01/c69b845f9974f5a4f59496ff3c48f981"
  from="Xavier Leroy &lt;Xavier.Leroy@i...&gt;"
  author="Xavier Leroy"
  date="2009-01-11T16:28:02"
  subject="Re: [Caml-list] Shared libraries with ocamlopt callable from C	(without main())?">
</msg>
</msg>
</msg>
</msg>
</thread>

<contents>
matthieu,
thanks for the interesting answer.
Unfortunately I can't build 'mycamlbuild.ml', and it is a bit too
advanced for me to understand.

Therefore I'll first go with your standard build commands. So - after
modifing the sources according to your suggestions I run:

BUILD
    ocamlopt -c add5.ml
    ocamlopt -c add5wrapperlib.c
    ocamlopt -o add5lib.native.so -ccopt -shared add5.cmx add5wrapperlib.o
    ocamlc.opt -ccopt -Iinclude -c main.c
    gcc -o maintest.native main.o -l:add5lib.native.so -L. -Wl,-rpath=.

EXECUTION
    cp add5lib.native.so  lib/
    ./maintest.native

ERROR
"maintest.native: add5wrapperlib.c:24: add5wrapper: Assertion `cbk' failed.
Aborted"

This is the referenced line:

    $ sed -n 24p add5wrapperlib.c
CAMLCBK_INIT(cbk, "add_five");


Any ideas what' wrong here?





2009/1/10 Matthieu Dubuget &lt;matthieu.dubuget@gmail.com&gt;:
&gt; Ben Jakb a écrit :
&gt;&gt; I try to create a static library called "libadd5wrapperlib.a" ( I know
&gt;&gt; kinda WTF ). So here is my simple example:
&gt;
&gt; I did not succeed (yet ;-) ) in making a static library…
&gt; I have an example with a shared one, though.
&gt;
&gt;&gt;
&gt;&gt; (Warning: You'll see a lot of bad code below, sorry for that, I work
&gt;&gt; hard to improve)
&gt;&gt;
&gt;&gt; =====  $ cat ./add5.ml =====
&gt;&gt;     (* the code doesnt add anything yet, it just gives 5 back *)
&gt;&gt;     let add_five () =
&gt;&gt;       let i = ref 0 in
&gt;&gt;         i := 5;
&gt;&gt;         !i;;
&gt;&gt;     Callback.register "add five" add_five;;
&gt;
&gt; I wrote :
&gt;
&gt;        Callback.register "add five" (fun () -&gt; 5)
&gt;
&gt;
&gt;&gt;
&gt;&gt;
&gt;&gt; =====  $ cat ./add5wrapperlib.c (Wraps the Ocaml code ) =====
&gt;&gt;     #include &lt;stdio.h&gt;
&gt;&gt;     #include &lt;caml/mlvalues.h&gt;
&gt;&gt;     #include &lt;caml/callback.h&gt;
&gt; #include &lt;assert.h&gt;
&gt;
&gt; #define CAMLCBK_INIT( callback, cbk_name) \
&gt;        static value *callback = NULL; \
&gt;        if (callback == NULL) callback = \
&gt;              caml_named_value(cbk_name);\
&gt;          assert(callback);
&gt;
&gt; static int init_done = 0;
&gt;
&gt; void init_lib(void){
&gt;  char *vide[1];
&gt;  vide[0] = NULL;
&gt;  if (!init_done){
&gt;        caml_startup(vide);
&gt;        init_done = 1;
&gt;  }
&gt; }
&gt;
&gt; int add5wrapper(){
&gt;  CAMLCBK_INIT(cbk, "add_five");
&gt;  return (Int_val ( caml_callback(*cbk, Val_unit)));
&gt; }
&gt;
&gt;
&gt;&gt; =====  $ cat ./include/libadd5wrapper.h (header file) =====
&gt; extern void init_lib(void);
&gt; extern int add5wrapper(void);
&gt;&gt;
&gt;&gt; =====  $ cat ./main.c =====
&gt;&gt;     #include &lt;stdio.h&gt;
&gt;&gt;     #include "libadd5wrapper.h"
&gt;&gt;     int main (int argc,char **argv){
&gt; init_lib();
&gt;&gt;        printf("Gimme - %d \n", add5wrapper());
&gt;&gt;        return 0;
&gt;&gt; }
&gt;&gt;
&gt;&gt; Now I try to BUILD the whole thing:
&gt;&gt; ----------------------------------------------
&gt;
&gt; ocamlopt -c add5.ml
&gt; ocamlopt -c add5wrapperlib.c
&gt; ocamlopt -o add5lib.native.so -ccopt -shared add5.cmx add5wrapperlib.o
&gt;
&gt; ocamlc.opt -ccopt -Iinclude -c main.c
&gt; gcc -o maintest.native main.o -l:add5lib.native.so -L. -Wl,-rpath=.
&gt;
&gt; In fact, i used ocamlbuild.
&gt;
&gt;
&gt; --------------myocamlbuild.ml -------------------------------------
&gt; open Ocamlbuild_plugin
&gt; open Command
&gt; open Outcome
&gt;
&gt; (* properties as (string * string) list read from "ocamlc -config" *)
&gt; let my_ocamlc_config =
&gt;  let rec sc s h =
&gt;    Scanf.sscanf s "%s@: %s@\n%n"
&gt;      begin fun k v n-&gt;
&gt;                let h' = (k, v) :: h in
&gt;                let len = String.length s in
&gt;                  if
&gt;                        len - n &lt;= 0
&gt;                  then
&gt;                        h'
&gt;                  else
&gt;                        sc (String.sub s n (len - n)) h'
&gt;      end in
&gt;    sc (Ocamlbuild_pack.My_unix.run_and_read "ocamlc -config") []
&gt;
&gt; let ext_o = List.assoc "ext_obj" my_ocamlc_config
&gt; let ext_so = List.assoc "ext_dll" my_ocamlc_config
&gt; let syst = List.assoc "system" my_ocamlc_config
&gt;
&gt; let split s ch =
&gt;  let x = ref [] in
&gt;  let rec go s =
&gt;    let pos = String.index s ch in
&gt;      x := (String.before s pos)::!x;
&gt;      go (String.after s (pos + 1))
&gt;  in
&gt;        try
&gt;      go s
&gt;        with Not_found -&gt; !x
&gt;
&gt; exception Found of string
&gt;
&gt; let pwd () =
&gt;  let env = Array.to_list (Unix.environment ()) in
&gt;  let rec search = function
&gt;          [] -&gt; ""
&gt;        | h :: tl -&gt;
&gt;                try
&gt;                  Scanf.sscanf h "PWD=%s" (fun x -&gt; x)
&gt;                with
&gt;                        _ -&gt; search tl in
&gt;        search env
&gt;
&gt; let split_nl s = split s '\n'
&gt;
&gt; let before_space s =
&gt;  try
&gt;    String.before s (String.index s ' ')
&gt;  with Not_found -&gt; s
&gt;
&gt; let uncap_module_path p =
&gt;  (Pathname.dirname p) / (String.uncapitalize (Pathname.basename p))
&gt;
&gt; let _ = dispatch begin function
&gt;  | After_rules -&gt;
&gt;          if syst = "linux_elf" then
&gt;                flag ["link"; "cmldll"]  (S[A"-ccopt";A"-shared"])
&gt;          else if syst = "mingw" then begin
&gt;                flag ["link";"cmldll"] (S[A"-output-obj"])
&gt;          end;
&gt;
&gt;          flag ["cmldll";"link";"byte"] (S[A"-custom"]);
&gt;
&gt;          rule "Mixed C-Ocaml native DLL: cmldll &amp; o* &amp; cmx* -&gt; native DLL
&gt; (.dll | .so)"
&gt;                ~dep:"%.cmldll"
&gt;                ~prod:("%.native" ^ ext_so)
&gt;                begin
&gt;                  fun env build -&gt;
&gt;                        let output = env ("%.native" ^ ext_so)
&gt;                        and input = env "%.cmldll" in
&gt;                        let dir = Pathname.dirname input in
&gt;
&gt;                        (* TODO: use functions of Pathname module? *)
&gt;                        let ext_o_files, moduls_files =
&gt;                          string_list_of_file input |&gt;
&gt;                                  List.partition (fun fic -&gt; Filename.check_suffix fic ".o") in
&gt;                        let objs = ext_o_files |&gt;
&gt;                                List.map Filename.chop_extension |&gt;
&gt;                                        List.map (fun fic -&gt; fic ^ ext_o) in
&gt;                        let cmxs = moduls_files |&gt;
&gt;                                List.map (fun modul -&gt;
&gt;                                                        (uncap_module_path modul) -.- "cmx") in
&gt;                        let deps = cmxs @ objs in
&gt;
&gt;                          List.iter ignore_good
&gt;                                (build (List.map (fun x -&gt; [dir/x]) deps));
&gt;
&gt;                          Cmd (S [!Options.ocamlopt;
&gt;                                          A"-o"; Px output;
&gt;                                          T (tags_of_pathname output++"ocaml"++"native"++"cmldll"++"link");
&gt;                                          atomize_paths deps
&gt;                                         ])
&gt;                end;
&gt;
&gt;      (* Allows to have .h copied in the _build directory *)
&gt;      dep ["file:main.c"] ["include/libadd5wrapper.h"];
&gt;
&gt;          flag ["include_libadd"] (S[A"-ccopt";A"-Iinclude"]);
&gt;          tag_file "main.c" ["include_libadd"];
&gt;
&gt;          rule "Compile maintest.native"
&gt;                ~deps:["main.o"; "add5lib.native.so"]
&gt;                ~prod:"maintest.native"
&gt;                begin fun _ _ -&gt;
&gt;                  let target = "maintest.native" in
&gt;                  let spc = "-Wl,-rpath=" ^ ((pwd ()) / (!Options.build_dir))  in
&gt;                        Cmd(
&gt;                          S[
&gt;                                A"gcc";
&gt;                                A"-o";A target;
&gt;                                A"main.o";
&gt;                                A"-l:add5lib.native.so";
&gt;                                A"-L."; A spc;
&gt;                          ])
&gt;                end;
&gt;
&gt;
&gt;  | _ -&gt; ()
&gt; end
&gt;
&gt; --------------end of myocamlbuild.ml -----------------------
&gt;
&gt; and the helper file add5lib.mlcdll:
&gt;
&gt; -------------add5lib.mlcdll----------------------
&gt; Add5
&gt; add5wrapperlib.o
&gt; -------------end of add5lib.mlcdll------------------
&gt;
&gt; do
&gt; ocamlbuild maintest.native
&gt; in order to build.
&gt;
&gt; This myocamlbuild.ml file is a "work in progress".
&gt; You can use it as you want if it can be of any help for you.
&gt;
&gt; Salutations
&gt;

</contents>

</message>

