From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: ** X-Spam-Status: No, score=2.1 required=5.0 tests=AWL,DNS_FROM_RFC_POST, SPF_NEUTRAL autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail1-relais-roc.national.inria.fr (mail1-relais-roc.national.inria.fr [192.134.164.82]) by yquem.inria.fr (Postfix) with ESMTP id DCA0EBBAF for ; Sat, 10 Jan 2009 19:18:05 +0100 (CET) X-IronPort-AV: E=Sophos;i="4.37,244,1231110000"; d="scan'208";a="22270447" Received: from concorde.inria.fr ([192.93.2.39]) by mail1-smtp-roc.national.inria.fr with ESMTP; 10 Jan 2009 19:18:05 +0100 Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by concorde.inria.fr (8.13.6/8.13.6) with ESMTP id n0AII5xC026574 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Sat, 10 Jan 2009 19:18:05 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AvABAOx0aEnRVdoKm2dsb2JhbACTUT4BAQEBAQgJCgkRsAaBAosCAQMBA4Vs X-IronPort-AV: E=Sophos;i="4.37,244,1231110000"; d="scan'208";a="33548821" Received: from mail-bw0-f10.google.com ([209.85.218.10]) by mail4-smtp-sop.national.inria.fr with ESMTP; 10 Jan 2009 19:18:04 +0100 Received: by bwz3 with SMTP id 3so25733288bwz.9 for ; Sat, 10 Jan 2009 10:18:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to :subject:in-reply-to:mime-version:content-type :content-transfer-encoding:content-disposition:references; bh=KrIdGoUkopVuvZ8w1AK0UcoLrXlV2ofDwE8v9I8QVzw=; b=CEbCVcild42AqWcroPI2niDttrx3ESNyclg1CUXj++Zl85PG7g6H01DfCLjFyFZhHH mTrGBkrjjym4RsPW9ZJT8Sjl36tPTa2p7DXdiwH1BuLalnnb2eWxAPI+2G4JBujaJ3CA IqDn3ykI1Gu31CLw6u9TsPjzHeougQKNVX/wc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:in-reply-to:mime-version :content-type:content-transfer-encoding:content-disposition :references; b=VdaRDZhyQKJlP/FUx5Gf+7Pw81dkzFY9FEsne+M3ZNwlSG9eoc0daUWN6zDi5EFAJS y1FbH4lNLlpFGbR8YWyJsZZMo90JZ2/XFusZcXpwykWWXx4+zINSDw+DUwNnbpPUPYwi 2GsXwamtd8iQ7VTsNbyOLUcUQlSSj8AkFndSI= Received: by 10.223.113.136 with SMTP id a8mr19626332faq.76.1231611481448; Sat, 10 Jan 2009 10:18:01 -0800 (PST) Received: by 10.223.108.209 with HTTP; Sat, 10 Jan 2009 10:18:01 -0800 (PST) Message-ID: Date: Sat, 10 Jan 2009 19:18:01 +0100 From: "Ben Jakb" To: "Florent Monnier" , caml-list@inria.fr Subject: Re: Shared libraries with ocamlopt callable from C (without main())? In-Reply-To: <200901101911.41594.monnier.florent@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=WINDOWS-1252 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline References: <49688B93.7080803@gmail.com> <200901101911.41594.monnier.florent@gmail.com> X-Miltered: at concorde with ID 4968E65D.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; ocamlopt:01 callable:01 ocaml:01 ocaml:01 cheers:01 matthieu:01 dubuget:01 stdio:01 mlvalues:01 lib:01 val:01 val:01 extern:01 lib:01 extern:01 > Can I leech this example to include it in my small ocaml/C wrapping tutor= ial ? > 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 : > Hi, > Can I leech this example to include it in my small ocaml/C wrapping tutor= ial ? > http://www.linux-nantes.org/%7Efmonnier/OCaml/ocaml-wrapping-c.php > > If so, do you want that your name appears or not or you don't mind ? > > Cheers > Florent > -- > Matthieu Dubuget a =E9crit : >> Ben Jakb a =E9crit : >> > I try to create a static library called "libadd5wrapperlib.a" ( I know >> > kinda WTF ). So here is my simple example: >> >> I did not succeed (yet ;-) ) in making a static library=85 >> I have an example with a shared one, though. >> >> > (Warning: You'll see a lot of bad code below, sorry for that, I work >> > hard to improve) >> > >> > =3D=3D=3D=3D=3D $ cat ./add5.ml =3D=3D=3D=3D=3D >> > (* the code doesnt add anything yet, it just gives 5 back *) >> > let add_five () =3D >> > let i =3D ref 0 in >> > i :=3D 5; >> > !i;; >> > Callback.register "add five" add_five;; >> >> I wrote : >> >> Callback.register "add five" (fun () -> 5) >> >> > =3D=3D=3D=3D=3D $ cat ./add5wrapperlib.c (Wraps the Ocaml code ) =3D= =3D=3D=3D=3D >> > #include >> > #include >> > #include >> >> #include >> >> #define CAMLCBK_INIT( callback, cbk_name) \ >> static value *callback =3D NULL; \ >> if (callback =3D=3D NULL) callback =3D \ >> caml_named_value(cbk_name);\ >> assert(callback); >> >> static int init_done =3D 0; >> >> void init_lib(void){ >> char *vide[1]; >> vide[0] =3D NULL; >> if (!init_done){ >> caml_startup(vide); >> init_done =3D 1; >> } >> } >> >> int add5wrapper(){ >> CAMLCBK_INIT(cbk, "add_five"); >> return (Int_val ( caml_callback(*cbk, Val_unit))); >> } >> >> > =3D=3D=3D=3D=3D $ cat ./include/libadd5wrapper.h (header file) =3D=3D= =3D=3D=3D >> >> extern void init_lib(void); >> extern int add5wrapper(void); >> >> > =3D=3D=3D=3D=3D $ cat ./main.c =3D=3D=3D=3D=3D >> > #include >> > #include "libadd5wrapper.h" >> > int main (int argc,char **argv){ >> >> init_lib(); >> >> > printf("Gimme - %d \n", add5wrapper()); >> > return 0; >> > } >> > >> > Now I try to BUILD the whole thing: >> > ---------------------------------------------- >> >> 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=3D. >> >> 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 =3D >> let rec sc s h =3D >> Scanf.sscanf s "%s@: %s@\n%n" >> begin fun k v n-> >> let h' =3D (k, v) :: h in >> let len =3D String.length s in >> if >> len - n <=3D 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 =3D List.assoc "ext_obj" my_ocamlc_config >> let ext_so =3D List.assoc "ext_dll" my_ocamlc_config >> let syst =3D List.assoc "system" my_ocamlc_config >> >> let split s ch =3D >> let x =3D ref [] in >> let rec go s =3D >> let pos =3D String.index s ch in >> x :=3D (String.before s pos)::!x; >> go (String.after s (pos + 1)) >> in >> try >> go s >> with Not_found -> !x >> >> exception Found of string >> >> let pwd () =3D >> let env =3D Array.to_list (Unix.environment ()) in >> let rec search =3D function >> [] -> "" >> >> | h :: tl -> >> >> try >> Scanf.sscanf h "PWD=3D%s" (fun x -> x) >> with >> _ -> search tl in >> search env >> >> let split_nl s =3D split s '\n' >> >> let before_space s =3D >> try >> String.before s (String.index s ' ') >> with Not_found -> s >> >> let uncap_module_path p =3D >> (Pathname.dirname p) / (String.uncapitalize (Pathname.basename p)) >> >> let _ =3D dispatch begin function >> >> | After_rules -> >> >> if syst =3D "linux_elf" then >> flag ["link"; "cmldll"] (S[A"-ccopt";A"-shared"]) >> else if syst =3D "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 & o* & cmx* -> native DLL >> (.dll | .so)" >> ~dep:"%.cmldll" >> ~prod:("%.native" ^ ext_so) >> begin >> fun env build -> >> let output =3D env ("%.native" ^ ext_so) >> and input =3D env "%.cmldll" in >> let dir =3D Pathname.dirname input in >> >> (* TODO: use functions of Pathname module? *) >> let ext_o_files, moduls_files =3D >> string_list_of_file input |> >> List.partition (fun fic -> Filename.chec= k_suffix fic ".o") in >> let objs =3D ext_o_files |> >> List.map Filename.chop_extension |> >> List.map (fun fic -> fic ^ ext_o) = in >> let cmxs =3D moduls_files |> >> List.map (fun modul -> >> (uncap_module_path= modul) -.- "cmx") in >> let deps =3D 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++"oca= ml"++"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 _ _ -> >> let target =3D "maintest.native" in >> let spc =3D "-Wl,-rpath=3D" ^ ((pwd ()) / (!Options.buil= d_dir)) in >> Cmd( >> S[ >> A"gcc"; >> A"-o";A target; >> A"main.o"; >> A"-l:add5lib.native.so"; >> A"-L."; A spc; >> ]) >> end; >> >> | _ -> () >> >> 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 >> >> _______________________________________________ >> Caml-list mailing list. Subscription management: >> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list >> Archives: http://caml.inria.fr >> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners >> Bug reports: http://caml.inria.fr/bin/caml-bugs >