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 mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by yquem.inria.fr (Postfix) with ESMTP id C631DBBAF for ; Sat, 10 Jan 2009 16:28:28 +0100 (CET) X-IronPort-AV: E=Sophos;i="4.37,244,1231110000"; d="scan'208";a="33544908" Received: from concorde.inria.fr ([192.93.2.39]) by mail4-smtp-sop.national.inria.fr with ESMTP; 10 Jan 2009 16:28:28 +0100 Received: from mail1-relais-roc.national.inria.fr (mail1-relais-roc.national.inria.fr [192.134.164.82]) by concorde.inria.fr (8.13.6/8.13.6) with ESMTP id n0AFSRsx024286 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Sat, 10 Jan 2009 16:28:28 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Ap4BAE5NaEnRVdoKm2dsb2JhbACTUT4BAQEBAQgJCgkRsCKBAosaAQMBA4Vs X-IronPort-AV: E=Sophos;i="4.37,244,1231110000"; d="scan'208";a="22266210" Received: from mail-bw0-f10.google.com ([209.85.218.10]) by mail1-smtp-roc.national.inria.fr with ESMTP; 10 Jan 2009 16:28:27 +0100 Received: by bwz3 with SMTP id 3so25610980bwz.9 for ; Sat, 10 Jan 2009 07:28:27 -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=bRJP7qiZQjqG+iLqD8lyewSiHj8T3h3ry3u1PniZiro=; b=huESKfPmkv0FwS02Ev3H9vAPg1xUu6hWMADpCjjQ3u/q9BB6bzX+sBKyCdG8DuaFct PoJjI4xCpM+cZcOETEqnggo3ANudmsfWkBcWKhwPnWSNXeVdh4V7XgRodswM3odbclSp x4h0Gcm6rAXH590P5cfO4u4Gmt8yjeO/uqTT8= 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=CPWjKr/e0t46yiAL+OSmMdwRpcalE6EwaqcG0fPUfvyLhBYMNOThMOWwVbAk8UiLbd GoNmur9dgvn+zDOHBN/CvUtJVYbx2v+MmDkBAawASlUoX1aRRxxMvRZlJVCxXfGBBpJV kHvtlpyuMN0b35ScdBpXBqTBC/AqtjEn22/zo= Received: by 10.223.109.20 with SMTP id h20mr19514435fap.41.1231601300933; Sat, 10 Jan 2009 07:28:20 -0800 (PST) Received: by 10.223.108.209 with HTTP; Sat, 10 Jan 2009 07:28:20 -0800 (PST) Message-ID: Date: Sat, 10 Jan 2009 16:28:20 +0100 From: "Ben Jakb" To: "matthieu.dubuget" , caml-list@inria.fr Subject: Re: [Caml-list] Shared libraries with ocamlopt callable from C (without main())? In-Reply-To: <49688B93.7080803@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=WINDOWS-1252 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline References: <49670917.3040103@gmail.com> <49688B93.7080803@gmail.com> X-Miltered: at concorde with ID 4968BE9B.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; ocamlopt:01 callable:01 matthieu:01 ml':01 ocamlopt:01 lib:01 -shared:01 cmx:01 ocamlc:01 gcc:01 lib:01 -wl:01 -rpath:01 assertion:01 matthieu:01 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=3D. 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 : > 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 >