From: "Ben Jakb" <ben.jakb@gmail.com>
To: "Florent Monnier" <monnier.florent@gmail.com>, caml-list@inria.fr
Subject: Re: Shared libraries with ocamlopt callable from C (without main())?
Date: Sat, 10 Jan 2009 19:18:01 +0100 [thread overview]
Message-ID: <fa75c1020901101018y57fd0813m40741808698b33f0@mail.gmail.com> (raw)
In-Reply-To: <200901101911.41594.monnier.florent@gmail.com>
> Can I leech this example to include it in my small ocaml/C wrapping tutorial ?
> 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 <monnier.florent@gmail.com>:
> Hi,
> Can I leech this example to include it in my small ocaml/C wrapping tutorial ?
> 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 écrit :
>> 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 <stdio.h>
>> > #include <caml/mlvalues.h>
>> > #include <caml/callback.h>
>>
>> #include <assert.h>
>>
>> #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 <stdio.h>
>> > #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
>>
>> _______________________________________________
>> 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
>
next prev parent reply other threads:[~2009-01-10 18:18 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-08 22:45 Ben Aurel
2009-01-09 8:21 ` [Caml-list] " Matthieu Dubuget
2009-01-09 8:44 ` [Caml-list] Shared libraries with ocamlopt callable from C(without main())? RABIH.ELCHAAR
2009-01-10 1:22 ` [Caml-list] Shared libraries with ocamlopt callable from C (without main())? Ben Jakb
2009-01-10 11:50 ` Matthieu Dubuget
2009-01-10 15:28 ` Ben Jakb
2009-01-10 15:36 ` Matthieu Dubuget
2009-01-10 18:08 ` Ben Jakb
[not found] ` <200901101911.41594.monnier.florent@gmail.com>
2009-01-10 18:18 ` Ben Jakb [this message]
2009-01-11 16:27 ` Xavier Leroy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=fa75c1020901101018y57fd0813m40741808698b33f0@mail.gmail.com \
--to=ben.jakb@gmail.com \
--cc=caml-list@inria.fr \
--cc=monnier.florent@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox