<?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/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())?"
  prev="2009/01/df2de1846d5559d3faa62662b822bba6"
  next="2009/01/a9e2313aff51e3555689baf7e4283478"
  prev-in-thread="2009/01/eabe0f1126a9d8c37e11c08054d99a36"
  next-in-thread="2009/01/7d3913d17469c862ee3e5ff3fceb4c1b"
  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>
Ben Jakb a écrit :
&gt; I try to create a static library called "libadd5wrapperlib.a" ( I know
&gt; kinda WTF ). So here is my simple example:

I did not succeed (yet ;-) ) in making a static library…
I have an example with a shared one, though.

&gt; 
&gt; (Warning: You'll see a lot of bad code below, sorry for that, I work
&gt; hard to improve)
&gt; 
&gt; =====  $ cat ./add5.ml =====
&gt;     (* the code doesnt add anything yet, it just gives 5 back *)
&gt;     let add_five () =
&gt;       let i = ref 0 in
&gt;         i := 5;
&gt;         !i;;
&gt;     Callback.register "add five" add_five;;

I wrote :

	Callback.register "add five" (fun () -&gt; 5)


&gt; 
&gt; 
&gt; =====  $ cat ./add5wrapperlib.c (Wraps the Ocaml code ) =====
&gt;     #include &lt;stdio.h&gt;
&gt;     #include &lt;caml/mlvalues.h&gt;
&gt;     #include &lt;caml/callback.h&gt;
#include &lt;assert.h&gt;

#define CAMLCBK_INIT( callback, cbk_name) \
        static value *callback = NULL; \
        if (callback == NULL) callback = \
              caml_named_value(cbk_name);\
          assert(callback);

static int init_done = 0;

void init_lib(void){
  char *vide[1];
  vide[0] = NULL;
  if (!init_done){
	caml_startup(vide);
	init_done = 1;
  }
}

int add5wrapper(){
  CAMLCBK_INIT(cbk, "add_five");
  return (Int_val ( caml_callback(*cbk, Val_unit)));
}


&gt; =====  $ cat ./include/libadd5wrapper.h (header file) =====
extern void init_lib(void);
extern int add5wrapper(void);
&gt; 
&gt; =====  $ cat ./main.c =====
&gt;     #include &lt;stdio.h&gt;
&gt;     #include "libadd5wrapper.h"
&gt;     int main (int argc,char **argv){
init_lib();
&gt;        printf("Gimme - %d \n", add5wrapper());
&gt;        return 0;
&gt; }
&gt; 
&gt; Now I try to BUILD the whole thing:
&gt; ----------------------------------------------

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=.

In fact, i used ocamlbuild.


--------------myocamlbuild.ml -------------------------------------
open Ocamlbuild_plugin
open Command
open Outcome

(* properties as (string * string) list read from "ocamlc -config" *)
let my_ocamlc_config =
  let rec sc s h =
    Scanf.sscanf s "%s@: %s@\n%n"
      begin fun k v n-&gt;
		let h' = (k, v) :: h in
		let len = String.length s in	
		  if
			len - n &lt;= 0
		  then
			h'
		  else
			sc (String.sub s n (len - n)) h'
      end in
    sc (Ocamlbuild_pack.My_unix.run_and_read "ocamlc -config") []

let ext_o = List.assoc "ext_obj" my_ocamlc_config
let ext_so = List.assoc "ext_dll" my_ocamlc_config
let syst = List.assoc "system" my_ocamlc_config

let split s ch =
  let x = ref [] in
  let rec go s =
    let pos = String.index s ch in
      x := (String.before s pos)::!x;
      go (String.after s (pos + 1))
  in
	try
      go s
	with Not_found -&gt; !x

exception Found of string

let pwd () =
  let env = Array.to_list (Unix.environment ()) in
  let rec search = function
	  [] -&gt; ""
	| h :: tl -&gt;
		try
		  Scanf.sscanf h "PWD=%s" (fun x -&gt; x)
		with
			_ -&gt; search tl in
	search env

let split_nl s = split s '\n'

let before_space s =
  try
    String.before s (String.index s ' ')
  with Not_found -&gt; s
	
let uncap_module_path p =
  (Pathname.dirname p) / (String.uncapitalize (Pathname.basename p))

let _ = dispatch begin function
  | After_rules -&gt;
	  if syst = "linux_elf" then
		flag ["link"; "cmldll"]  (S[A"-ccopt";A"-shared"])	
	  else if syst = "mingw" then begin
		flag ["link";"cmldll"] (S[A"-output-obj"])
	  end;

	  flag ["cmldll";"link";"byte"] (S[A"-custom"]);
	  	
	  rule "Mixed C-Ocaml native DLL: cmldll &amp; o* &amp; cmx* -&gt; native DLL
(.dll | .so)"
		~dep:"%.cmldll"
		~prod:("%.native" ^ ext_so)
		begin
		  fun env build -&gt;
			let output = env ("%.native" ^ ext_so)
			and input = env "%.cmldll" in
			let dir = Pathname.dirname input in

			(* TODO: use functions of Pathname module? *)
			let ext_o_files, moduls_files =
			  string_list_of_file input |&gt;
				  List.partition (fun fic -&gt; Filename.check_suffix fic ".o") in
			let objs = ext_o_files |&gt;
				List.map Filename.chop_extension |&gt;
					List.map (fun fic -&gt; fic ^ ext_o) in
			let cmxs = moduls_files |&gt;
				List.map (fun modul -&gt;
							(uncap_module_path modul) -.- "cmx") in
			let deps = cmxs @ objs in

			  List.iter ignore_good
				(build (List.map (fun x -&gt; [dir/x]) deps));

			  Cmd (S [!Options.ocamlopt;
					  A"-o"; Px output;
					  T (tags_of_pathname output++"ocaml"++"native"++"cmldll"++"link");
					  atomize_paths deps
					 ])
		end;

      (* Allows to have .h copied in the _build directory *)
      dep ["file:main.c"] ["include/libadd5wrapper.h"];

	  flag ["include_libadd"] (S[A"-ccopt";A"-Iinclude"]);
	  tag_file "main.c" ["include_libadd"];

	  rule "Compile maintest.native"
		~deps:["main.o"; "add5lib.native.so"]
		~prod:"maintest.native"
		begin fun _ _ -&gt;
		  let target = "maintest.native" in
		  let spc = "-Wl,-rpath=" ^ ((pwd ()) / (!Options.build_dir))  in
			Cmd(
			  S[
				A"gcc";
				A"-o";A target;
				A"main.o";
				A"-l:add5lib.native.so";
				A"-L."; A spc;
			  ])
		end;


  | _ -&gt; ()
end

--------------end of myocamlbuild.ml -----------------------

and the helper file add5lib.mlcdll:

-------------add5lib.mlcdll----------------------
Add5
add5wrapperlib.o
-------------end of add5lib.mlcdll------------------

do
ocamlbuild maintest.native
in order to build.

This myocamlbuild.ml file is a "work in progress".
You can use it as you want if it can be of any help for you.

Salutations

</contents>

</message>

