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=1.7 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 mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by yquem.inria.fr (Postfix) with ESMTP id 1FF4EBBAF for ; Sat, 10 Jan 2009 12:50:49 +0100 (CET) X-IronPort-AV: E=Sophos;i="4.37,243,1231110000"; d="scan'208";a="21284813" Received: from concorde.inria.fr ([192.93.2.39]) by mail3-smtp-sop.national.inria.fr with ESMTP; 10 Jan 2009 12:50:48 +0100 Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by concorde.inria.fr (8.13.6/8.13.6) with ESMTP id n0ABom9b021423 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Sat, 10 Jan 2009 12:50:48 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: ApMBALEaaEnRVYC/kGdsb2JhbACTUj4BAQEBCQkMBxEDr2IIeosiAQMBA4VsgiQ X-IronPort-AV: E=Sophos;i="4.37,243,1231110000"; d="scan'208";a="21284812" Received: from fk-out-0910.google.com ([209.85.128.191]) by mail3-smtp-sop.national.inria.fr with ESMTP; 10 Jan 2009 12:50:47 +0100 Received: by fk-out-0910.google.com with SMTP id e30so4690036fke.9 for ; Sat, 10 Jan 2009 03:50:47 -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:reply-to :user-agent:mime-version:to:cc:subject:references:in-reply-to :x-enigmail-version:openpgp:content-type:content-transfer-encoding; bh=ChwPTZD32X2iP+g1YigoSwq3DjQ9sZjx3xotUc+9rbU=; b=dpGiEOJyYYwrzyjAYF0nZsM1vBVryBl+xkguD515O309fTtvt3Ip32pYxSYfAYc5pu P3bj0us+ZZLRWc3m5weoqEid/GswMCz5Mk4fwjAuf7u6iYEkj78X/JnlqE/ruNQYxepq fC/CfZ5OvbiC3Z42qPiplX6tmHwJjuzS5h7G0= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:reply-to:user-agent:mime-version:to:cc:subject :references:in-reply-to:x-enigmail-version:openpgp:content-type :content-transfer-encoding; b=X31liY3ca+tv4c4X86xKNs5dhP07BDV93jaTJWTCBBunXDomg4ufUgscnjhSdHFyh4 nwOtsWlVClLS0qVkVrxVCop3sb2SpHYpvZTSJIm5jWIUZp+eT/wLchlXKnP0BkXaIx8S hQ10ilseFZ0qSekhlvLmlqeAEqugmHJrUw6M8= Received: by 10.103.1.5 with SMTP id d5mr9567136mui.29.1231588247223; Sat, 10 Jan 2009 03:50:47 -0800 (PST) Received: from ?192.168.1.10? (8.75.197-77.rev.gaoland.net [77.197.75.8]) by mx.google.com with ESMTPS id e8sm35623761muf.0.2009.01.10.03.50.45 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sat, 10 Jan 2009 03:50:46 -0800 (PST) Message-ID: <49688B93.7080803@gmail.com> Date: Sat, 10 Jan 2009 12:50:43 +0100 From: Matthieu Dubuget Reply-To: matthieu.dubuget@gmail.com User-Agent: Thunderbird 2.0.0.19 (X11/20090105) MIME-Version: 1.0 To: caml-list@inria.fr Cc: Ben Jakb Subject: Re: [Caml-list] Shared libraries with ocamlopt callable from C (without main())? References: <49670917.3040103@gmail.com> In-Reply-To: X-Enigmail-Version: 0.95.0 OpenPGP: id=F60AB8F5 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Miltered: at concorde with ID 49688B98.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; matthieu:01 dubuget:01 matthieu:01 dubuget:01 ocamlopt:01 callable:01 ocaml:01 stdio:01 mlvalues:01 lib:01 val:01 val:01 extern:01 lib:01 extern:01 Ben Jakb a écrit : > 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… 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) > > ===== $ cat ./add5.ml ===== > (* the code doesnt add anything yet, it just gives 5 back *) > let add_five () = > let i = ref 0 in > i := 5; > !i;; > Callback.register "add five" add_five;; I wrote : Callback.register "add five" (fun () -> 5) > > > ===== $ cat ./add5wrapperlib.c (Wraps the Ocaml code ) ===== > #include > #include > #include #include #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))); } > ===== $ cat ./include/libadd5wrapper.h (header file) ===== extern void init_lib(void); extern int add5wrapper(void); > > ===== $ cat ./main.c ===== > #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=. 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-> 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") [] 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 -> !x 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 split_nl s = split s '\n' let before_space s = try String.before s (String.index s ' ') with Not_found -> s let uncap_module_path p = (Pathname.dirname p) / (String.uncapitalize (Pathname.basename p)) let _ = dispatch begin function | After_rules -> 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 & o* & cmx* -> native DLL (.dll | .so)" ~dep:"%.cmldll" ~prod:("%.native" ^ ext_so) begin fun env build -> 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 |> 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"++"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 = "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; | _ -> () 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