diff -urN ./files/camlpdfc.mlcdll ./files-modified/camlpdfc.mlcdll --- ./files/camlpdfc.mlcdll 1970-01-01 01:00:00.000000000 +0100 +++ ./files-modified/camlpdfc.mlcdll 2009-01-20 22:16:52.000000000 +0100 @@ -0,0 +1,2 @@ +Cpdflibc +cpdflibwrapper.o diff -urN ./files/cpdflibc.ml ./files-modified/cpdflibc.ml --- ./files/cpdflibc.ml 2009-01-20 18:00:51.000000000 +0100 +++ ./files-modified/cpdflibc.ml 2009-01-20 22:23:27.000000000 +0100 @@ -1,2 +1,4 @@ (* cpdflibc.ml *) let twice x = x * 2 + +let _ = Callback.register "twice" twice diff -urN ./files/cpdflibwrapper.c ./files-modified/cpdflibwrapper.c --- ./files/cpdflibwrapper.c 2009-01-20 18:00:51.000000000 +0100 +++ ./files-modified/cpdflibwrapper.c 2009-01-20 22:18:58.000000000 +0100 @@ -2,10 +2,33 @@ #include #include #include +#include +#define CAMLPDFLIB_CAMLCBK_INIT( callback, cbk_name) \ + static value *callback = NULL; \ + if (callback == NULL) callback = \ + caml_named_value(cbk_name);\ + assert(callback); + +static int cpdflibc_init_done = 0; + +void +init_cpdflib () +{ + char *vide[1]; + vide[0] = NULL; + if (!cpdflibc_init_done) + { + caml_startup (vide); + cpdflibc_init_done = 1; + } +} + int twice_c (int i) { - CAMLlocal1 (result); - result = caml_callback(*caml_named_value("twice"), Val_int(i)); - return(0); + CAMLparam0(); + CAMLlocal1(res); + CAMLPDFLIB_CAMLCBK_INIT(cbk, "twice"); + res = caml_callback(*cbk, Val_int(i)); + CAMLreturnT(int, Int_val(res)); } diff -urN ./files/cpdflibwrapper.h ./files-modified/cpdflibwrapper.h --- ./files/cpdflibwrapper.h 2009-01-20 18:00:51.000000000 +0100 +++ ./files-modified/cpdflibwrapper.h 2009-01-20 22:22:45.000000000 +0100 @@ -1,3 +1,4 @@ /* cpdflibwrapper.h */ -int twice (int); +void init_cpdflib(); +int twice_c (int); diff -urN ./files/myocamlbuild.ml ./files-modified/myocamlbuild.ml --- ./files/myocamlbuild.ml 1970-01-01 01:00:00.000000000 +0100 +++ ./files-modified/myocamlbuild.ml 2009-01-20 22:19:59.000000000 +0100 @@ -0,0 +1,103 @@ +open Ocamlbuild_plugin +open Command +open Outcome + +let (ext_o, ext_so, syst) = + let my_ocamlc_config = + let rec sc s h = + Scanf.sscanf s "%s@: %s@\n%n" + begin fun k v n -> + let h' = (k, v) :: h in + let len = String.length s in + if + len - n <= 0 + then + h' + else + sc (String.sub s n (len - n)) h' + end in + sc (Ocamlbuild_pack.My_unix.run_and_read "ocamlc -config") [] in + match + List.map + (fun x -> List.assoc x my_ocamlc_config) + ["ext_obj"; "ext_dll"; "system";] + with + [ext_o; ext_so; syst] -> ext_o, ext_so, syst + | _ -> assert false + +exception Found of string + +let pwd () = + let env = Array.to_list (Unix.environment ()) in + let rec search = function + [] -> "" + | h :: tl -> + try + Scanf.sscanf h "PWD=%s" (fun x -> x) + with + _ -> search tl in + search env + +let uncap_module_path p = + (Pathname.dirname p) / (String.uncapitalize (Pathname.basename p)) + +let _ = dispatch begin function + + | After_rules -> + + flag ["link";"mlcdll"] (S[A"-output-obj"]); + + rule "Mixed C-Ocaml native DLL: mlcdll & o* & cmx* -> native DLL (.dll | .so)" + ~dep:"%.mlcdll" + ~prod:("%.native" ^ ext_so) + begin + fun env build -> + let output = env ("%.native" ^ ext_so) + and input = env "%.mlcdll" in + let dir = Pathname.dirname input in + + (* TODO: use functions of Pathname module? *) + let ext_o_files, moduls_files = + string_list_of_file input |> + List.partition (fun fic -> Filename.check_suffix fic ".o") in + let objs = ext_o_files |> + List.map Filename.chop_extension |> + List.map (fun fic -> fic ^ ext_o) in + let cmxs = moduls_files |> + List.map (fun modul -> + (uncap_module_path modul) -.- "cmx") in + let deps = cmxs @ objs in + + List.iter ignore_good + (build (List.map (fun x -> [dir/x]) deps)); + + Cmd (S [!Options.ocamlopt; + A"-o"; Px output; + T (tags_of_pathname output++"ocaml"++"native"++"mlcdll"++"link"); + atomize_paths deps + ]) + end; + + (* Allows to have .h copied in the _build directory *) + dep ["file:cpdflibwrapper.c"] ["cpdflibwrapper.h"]; + dep ["file:test.c"]["cpdflibwrapper.h"]; + + rule "Compile test.native" + ~deps:["test.o"; "camlpdfc.native.so"] + ~prod:"test.native" + begin fun _ _ -> + let target = "test.native" in + let spc = "-Wl,-rpath=" ^ ((pwd ()) / (!Options.build_dir)) in + Cmd( + S[ + A"gcc"; + A"-o";A target; + A"test.o"; + A"-l:camlpdfc.native.so"; + A"-L."; A spc; + ]) + end; + + + | _ -> () +end diff -urN ./files/test.c ./files-modified/test.c --- ./files/test.c 2009-01-20 18:00:51.000000000 +0100 +++ ./files-modified/test.c 2009-01-20 22:20:29.000000000 +0100 @@ -4,6 +4,7 @@ int main () { + init_cpdflib(); printf("Twice two is %i\n", twice_c(2)); return(0); }