From: "Ben Jakb" <ben.jakb@gmail.com>
To: "matthieu.dubuget" <matthieu.dubuget@gmail.com>, caml-list@inria.fr
Subject: Re: [Caml-list] Shared libraries with ocamlopt callable from C (without main())?
Date: Sat, 10 Jan 2009 16:28:20 +0100 [thread overview]
Message-ID: <fa75c1020901100728t71d7562qd9c2c52fb2e51696@mail.gmail.com> (raw)
In-Reply-To: <49688B93.7080803@gmail.com>
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=.
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 <matthieu.dubuget@gmail.com>:
> 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
>
next prev parent reply other threads:[~2009-01-10 15:28 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 [this message]
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
2009-01-11 16:27 ` [Caml-list] " 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=fa75c1020901100728t71d7562qd9c2c52fb2e51696@mail.gmail.com \
--to=ben.jakb@gmail.com \
--cc=caml-list@inria.fr \
--cc=matthieu.dubuget@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