<?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/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())?"
  prev="2009/01/7504deae4c49192ff0d96985d8da8c12"
  next="2009/01/c69b845f9974f5a4f59496ff3c48f981"
  prev-in-thread="2009/01/7504deae4c49192ff0d96985d8da8c12"
  next-in-thread="2009/01/c69b845f9974f5a4f59496ff3c48f981"
  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>
&gt; Can I leech this example to include it in my small ocaml/C wrapping tutorial ?
&gt; http://www.linux-nantes.org/%7Efmonnier/OCaml/ocaml-wrapping-c.php

this would be great (imho). Your articles where the starting point for
my attempts.


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

</contents>

</message>

