* [Caml-list] Static linking via Ctypes? @ 2014-03-25 14:54 dbenjamin 2014-03-25 15:04 ` Bruno Deferrari 2014-03-25 15:10 ` Daniel Bünzli 0 siblings, 2 replies; 12+ messages in thread From: dbenjamin @ 2014-03-25 14:54 UTC (permalink / raw) To: caml-list I'm using Ctypes to interface with a dynamic library, but in addition to the interface provided the library I have some helper functions (written in C, against the same library) that I'd also like to call via Ctypes. Is there any way to achieve this via static linking or am I required to build another shared object? ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Static linking via Ctypes? 2014-03-25 14:54 [Caml-list] Static linking via Ctypes? dbenjamin @ 2014-03-25 15:04 ` Bruno Deferrari 2014-03-25 15:11 ` Dan Benjamin 2014-03-25 15:10 ` Daniel Bünzli 1 sibling, 1 reply; 12+ messages in thread From: Bruno Deferrari @ 2014-03-25 15:04 UTC (permalink / raw) To: dbenjamin; +Cc: caml-list On Tue, Mar 25, 2014 at 11:54 AM, <dbenjamin@janestreet.com> wrote: > I'm using Ctypes to interface with a dynamic library, but in addition to the > interface provided the library I have some helper functions (written in C, > against the same library) that I'd also like to call via Ctypes. Is there any > way to achieve this via static linking or am I required to build another > shared object? > Static linking works. I was in this same situation yesterday, and adding the .o files that were generated from C sources to the linking step did the trick. If you are trying to link a .a file, you may have to pass the -force_load option to the linker to force it to include it, otherwise it may see that none of the symbols there are being referenced directly and decide to not include it (this happened to me when using clang in OSX). > -- > Caml-list mailing list. Subscription management and archives: > https://sympa.inria.fr/sympa/arc/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs -- BD ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Static linking via Ctypes? 2014-03-25 15:04 ` Bruno Deferrari @ 2014-03-25 15:11 ` Dan Benjamin 2014-03-25 15:24 ` David Sheets 0 siblings, 1 reply; 12+ messages in thread From: Dan Benjamin @ 2014-03-25 15:11 UTC (permalink / raw) To: Bruno Deferrari; +Cc: caml-list I am passing -force_load, as well as --whole-archive (in case that makes a difference), and I have the following situation: - readelf -s shows that the function that I wish to call exists in the executable - running the executable results in Dl.DL_error("undefined symbol") for the same function, corresponding to the line of code where I call Foreign.foreign. Am I going about this wrongly? On Tue, Mar 25, 2014 at 11:04 AM, Bruno Deferrari <utizoc@gmail.com> wrote: > On Tue, Mar 25, 2014 at 11:54 AM, <dbenjamin@janestreet.com> wrote: >> I'm using Ctypes to interface with a dynamic library, but in addition to the >> interface provided the library I have some helper functions (written in C, >> against the same library) that I'd also like to call via Ctypes. Is there any >> way to achieve this via static linking or am I required to build another >> shared object? >> > > Static linking works. I was in this same situation yesterday, and > adding the .o files that were generated from C sources to the linking > step did the trick. > > If you are trying to link a .a file, you may have to pass the > -force_load option to the linker to force it to include it, otherwise > it may see that none of the symbols there are being referenced > directly and decide to not include it (this happened to me when using > clang in OSX). > >> -- >> Caml-list mailing list. Subscription management and archives: >> https://sympa.inria.fr/sympa/arc/caml-list >> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners >> Bug reports: http://caml.inria.fr/bin/caml-bugs > > > > -- > BD ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Static linking via Ctypes? 2014-03-25 15:11 ` Dan Benjamin @ 2014-03-25 15:24 ` David Sheets 2014-03-25 17:55 ` Dan Benjamin 0 siblings, 1 reply; 12+ messages in thread From: David Sheets @ 2014-03-25 15:24 UTC (permalink / raw) To: Dan Benjamin; +Cc: Bruno Deferrari, O Caml On Tue, Mar 25, 2014 at 3:11 PM, Dan Benjamin <dbenjamin@janestreet.com> wrote: > I am passing -force_load, as well as --whole-archive (in case that > makes a difference), and I have the following situation: > > - readelf -s shows that the function that I wish to call exists in the > executable > - running the executable results in Dl.DL_error("undefined symbol") > for the same function, corresponding to the line of code where I call > Foreign.foreign. > > Am I going about this wrongly? I did <https://github.com/dsheets/ocaml-unix-unistd/blob/master/lib/unix_unistd_stubs.c#L61> and <https://github.com/dsheets/ocaml-unix-unistd/blob/master/lib/ctypes/unix_unistd.ml#L32> to require a static link without stub generation in addition to ocamlmklib on the .ml and .o files. Unfortunately, this is not very portable (or sane). I believe that <https://github.com/ocamllabs/ocaml-ctypes/issues/96> may be related. Hope this helps, David > On Tue, Mar 25, 2014 at 11:04 AM, Bruno Deferrari <utizoc@gmail.com> wrote: >> On Tue, Mar 25, 2014 at 11:54 AM, <dbenjamin@janestreet.com> wrote: >>> I'm using Ctypes to interface with a dynamic library, but in addition to the >>> interface provided the library I have some helper functions (written in C, >>> against the same library) that I'd also like to call via Ctypes. Is there any >>> way to achieve this via static linking or am I required to build another >>> shared object? >>> >> >> Static linking works. I was in this same situation yesterday, and >> adding the .o files that were generated from C sources to the linking >> step did the trick. >> >> If you are trying to link a .a file, you may have to pass the >> -force_load option to the linker to force it to include it, otherwise >> it may see that none of the symbols there are being referenced >> directly and decide to not include it (this happened to me when using >> clang in OSX). >> >>> -- >>> Caml-list mailing list. Subscription management and archives: >>> https://sympa.inria.fr/sympa/arc/caml-list >>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners >>> Bug reports: http://caml.inria.fr/bin/caml-bugs >> >> >> >> -- >> BD > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa.inria.fr/sympa/arc/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Static linking via Ctypes? 2014-03-25 15:24 ` David Sheets @ 2014-03-25 17:55 ` Dan Benjamin 2014-03-25 21:19 ` Jeremy Yallop 0 siblings, 1 reply; 12+ messages in thread From: Dan Benjamin @ 2014-03-25 17:55 UTC (permalink / raw) To: David Sheets; +Cc: Bruno Deferrari, O Caml That does work, thanks very much. Are there plans to add anything similar to Ctypes? On Tue, Mar 25, 2014 at 11:24 AM, David Sheets <sheets@alum.mit.edu> wrote: > On Tue, Mar 25, 2014 at 3:11 PM, Dan Benjamin <dbenjamin@janestreet.com> wrote: >> I am passing -force_load, as well as --whole-archive (in case that >> makes a difference), and I have the following situation: >> >> - readelf -s shows that the function that I wish to call exists in the >> executable >> - running the executable results in Dl.DL_error("undefined symbol") >> for the same function, corresponding to the line of code where I call >> Foreign.foreign. >> >> Am I going about this wrongly? > > I did > > <https://github.com/dsheets/ocaml-unix-unistd/blob/master/lib/unix_unistd_stubs.c#L61> > > and > > <https://github.com/dsheets/ocaml-unix-unistd/blob/master/lib/ctypes/unix_unistd.ml#L32> > > to require a static link without stub generation in addition to > ocamlmklib on the .ml and .o files. > > Unfortunately, this is not very portable (or sane). I believe that > <https://github.com/ocamllabs/ocaml-ctypes/issues/96> may be related. > > Hope this helps, > > David > >> On Tue, Mar 25, 2014 at 11:04 AM, Bruno Deferrari <utizoc@gmail.com> wrote: >>> On Tue, Mar 25, 2014 at 11:54 AM, <dbenjamin@janestreet.com> wrote: >>>> I'm using Ctypes to interface with a dynamic library, but in addition to the >>>> interface provided the library I have some helper functions (written in C, >>>> against the same library) that I'd also like to call via Ctypes. Is there any >>>> way to achieve this via static linking or am I required to build another >>>> shared object? >>>> >>> >>> Static linking works. I was in this same situation yesterday, and >>> adding the .o files that were generated from C sources to the linking >>> step did the trick. >>> >>> If you are trying to link a .a file, you may have to pass the >>> -force_load option to the linker to force it to include it, otherwise >>> it may see that none of the symbols there are being referenced >>> directly and decide to not include it (this happened to me when using >>> clang in OSX). >>> >>>> -- >>>> Caml-list mailing list. Subscription management and archives: >>>> https://sympa.inria.fr/sympa/arc/caml-list >>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners >>>> Bug reports: http://caml.inria.fr/bin/caml-bugs >>> >>> >>> >>> -- >>> BD >> >> -- >> Caml-list mailing list. Subscription management and archives: >> https://sympa.inria.fr/sympa/arc/caml-list >> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners >> Bug reports: http://caml.inria.fr/bin/caml-bugs ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Static linking via Ctypes? 2014-03-25 17:55 ` Dan Benjamin @ 2014-03-25 21:19 ` Jeremy Yallop 2014-03-25 21:37 ` Milan Stanojević 0 siblings, 1 reply; 12+ messages in thread From: Jeremy Yallop @ 2014-03-25 21:19 UTC (permalink / raw) To: Dan Benjamin; +Cc: David Sheets, Bruno Deferrari, O Caml David Sheets <sheets@alum.mit.edu> wrote: > I did > > <https://github.com/dsheets/ocaml-unix-unistd/blob/master/lib/unix_unistd_stubs.c#L61> > > and > > <https://github.com/dsheets/ocaml-unix-unistd/blob/master/lib/ctypes/unix_unistd.ml#L32> > > to require a static link without stub generation in addition to > ocamlmklib on the .ml and .o files. > > Unfortunately, this is not very portable (or sane). On 25/03/2014, Dan Benjamin <dbenjamin@janestreet.com> wrote: > That does work, thanks very much. Are there plans to add anything > similar to Ctypes? Not exactly, since the stub generation support in the next ctypes release resolves these issues in a different way. In the current release (0.2.3) setting up foreign calls and linking are both entirely dynamic. Stub generation will make it possible to link statically as well. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Static linking via Ctypes? 2014-03-25 21:19 ` Jeremy Yallop @ 2014-03-25 21:37 ` Milan Stanojević 2014-03-25 23:14 ` Jeremy Yallop 0 siblings, 1 reply; 12+ messages in thread From: Milan Stanojević @ 2014-03-25 21:37 UTC (permalink / raw) To: Jeremy Yallop; +Cc: Dan Benjamin, David Sheets, Bruno Deferrari, O Caml > Not exactly, since the stub generation support in the next ctypes > release resolves these issues in a different way. In the current > release (0.2.3) setting up foreign calls and linking are both entirely > dynamic. Stub generation will make it possible to link statically as > well. Can you tell us how would this work exactly? Let's say I have a function "foo" in my C file (that I want to link statically) and I want to give use it in ocaml with a ctype (void @-> returning int) What would I need to say in my ocaml program and do I have to tell anything to my build system? ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Static linking via Ctypes? 2014-03-25 21:37 ` Milan Stanojević @ 2014-03-25 23:14 ` Jeremy Yallop 2014-03-26 16:24 ` Travis Brady 2014-03-26 17:25 ` Milan Stanojević 0 siblings, 2 replies; 12+ messages in thread From: Jeremy Yallop @ 2014-03-25 23:14 UTC (permalink / raw) To: Milan Stanojević; +Cc: Dan Benjamin, David Sheets, Bruno Deferrari, O Caml I wrote: > Not exactly, since the stub generation support in the next ctypes > release resolves these issues in a different way. In the current > release (0.2.3) setting up foreign calls and linking are both entirely > dynamic. Stub generation will make it possible to link statically as > well. Milan Stanojević asked: > Can you tell us how would this work exactly? > Let's say I have a function "foo" in my C file (that I want to link > statically) and I want to give use it in ocaml with a ctype (void @-> > returning int) > What would I need to say in my ocaml program and do I have to tell > anything to my build system? With the current release of ctypes we'd bind 'foo' like this: let f = foreign "foo" (void @-> returning int) The 'foreign' function searches for the symbol "foo" and sets up the call; the return value is an OCaml function that we can call immediately. val f : unit -> int With stub generation as implemented in the git master branch the call to 'foreign' changes slightly. Instead of calling 'foreign' just once, we're going to call it once for each stage of generation. The way we do this is to abstract over 'foreign' with a functor. (Note the similarity to the original binding of 'f' above.) module Bindings (F : Cstubs.FOREIGN) = struct let f = F.foreign "foo" (void @-> returning int) end The first application of the functor generates C: Cstubs.write_c std_formatter ~prefix:"foo_" (module Bindings) The output is a wrapper for the C function 'foo' that marshals and unmarshals arguments and return values as needed. The second application generates OCaml: Cstubs.write_ml std_formatter ~prefix:"foo_" (module Bindings) The output is an OCaml module that we can pass to 'Bindings' for the third and final application, which links together the declaration of 'f' and the generated code: Bindings(Generated_ML) As with the dynamic binding, this gives us an OCaml function that we can call without further ado: val f : unit -> int The build process is reasonably straightforward. Since we're generating code, there are more steps than with the dynamic version, but we're less likely to need obscure linker flags. A typical approach is to place the bindings functor in one file -- foo_binding.ml, say: module Bindings(F : Cstubs.FOREIGN) = struct let foo = F.foreign "foo" Ctypes.(void @-> returning int) end and the calls to 'write_c' and 'write_ml' other files. I'll put the call to 'write_c' along with code to print out the headers used in generate_c.ml: let () = print_endline "#include <ctypes/cstubs_internals.h>"; print_endline "#include \"foo.h\""; Cstubs.write_c Format.std_formatter ~prefix:"foo_" (module Foo_binding.Bindings) The call to 'write_ml' goes in generate_ml.ml: let () = Cstubs.write_ml Format.std_formatter ~prefix:"foo_" (module Foo_binding.Bindings) Then we can compile and run the two programs to generate the stub code: $ ocamlfind ocamlc -c -package ctypes.stubs \ foo_binding.ml generate_c.ml generate_ml.ml $ ocamlfind ocamlc -o generate_ml.native -linkpkg -package ctypes.stubs \ foo_binding.cmo generate_ml.cmo $ ./generate_ml.native > generated.ml $ ocamlfind ocamlc -o generate_c.native -linkpkg -package ctypes.stubs \ foo_binding.cmo generate_c.cmo $ ./generate_c.native > generated_c_stubs.c We can then compile the stub code and link it in with the bindings functor and the library containing 'foo': $ ocamlfind ocamlc -c -package ctypes.stubs -I `ocamlc -where`/.. \ generated_c_stubs.c generated.ml $ ocamlfind ocamlmklib -o foo -linkpkg -package ctypes.stubs \ generated_c_stubs.o generated.cmo foo_binding.cmo -L. -lfoo Finally, we can load the code and call the 'foo' function: $ ocaml -short-paths OCaml version 4.01.0 # #use "topfind";; [...] # #require "ctypes.stubs";; [...] # #load "foo.cma";; # include Foo_binding.Bindings(Generated);; val foo : unit -> int = <fun> # foo ();; foo called - : int = 3 The full stub generation interface (which is actually just the 'write_ml' and 'write_c' functions) is here: https://github.com/ocamllabs/ocaml-ctypes/blob/1e1634/src/cstubs/cstubs.mli Jeremy ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Static linking via Ctypes? 2014-03-25 23:14 ` Jeremy Yallop @ 2014-03-26 16:24 ` Travis Brady 2014-03-26 17:17 ` Daniel Bünzli 2014-03-26 17:25 ` Milan Stanojević 1 sibling, 1 reply; 12+ messages in thread From: Travis Brady @ 2014-03-26 16:24 UTC (permalink / raw) To: Jeremy Yallop Cc: Milan Stanojević, Dan Benjamin, David Sheets, Bruno Deferrari, O Caml [-- Attachment #1: Type: text/plain, Size: 5794 bytes --] This thread is timely for me because I'm attempting to get my ctypes-based liblinear[1] bindings to behave (with oasis) but thus far have come up short. I've followed the instructions in [2] and tried to crib from onanomsg and ocaml-picosat, but am only able to support either the toplevel OR linking in binaries. But not both. So currently I can make binaries, but I'd love to be able to #require this in utop for interactive ipython-like usage. Is there a canonical solution to this problem for oasis users? I'm considering trying what jane st did with re2 and bundling liblinear up with my bindings and cribbing from their build process, but ideally this would all just work with oasis. thank you Travis [1] https://github.com/travisbrady/oliblinear [2] https://github.com/ocamllabs/ocaml-ctypes/issues/51#issuecomment-30729675 On Tue, Mar 25, 2014 at 6:14 PM, Jeremy Yallop <yallop@gmail.com> wrote: > I wrote: > > Not exactly, since the stub generation support in the next ctypes > > release resolves these issues in a different way. In the current > > release (0.2.3) setting up foreign calls and linking are both entirely > > dynamic. Stub generation will make it possible to link statically as > > well. > > Milan Stanojević asked: > > Can you tell us how would this work exactly? > > Let's say I have a function "foo" in my C file (that I want to link > > statically) and I want to give use it in ocaml with a ctype (void @-> > > returning int) > > What would I need to say in my ocaml program and do I have to tell > > anything to my build system? > > With the current release of ctypes we'd bind 'foo' like this: > > let f = foreign "foo" (void @-> returning int) > > The 'foreign' function searches for the symbol "foo" and sets up the > call; the return value is an OCaml function that we can call > immediately. > > val f : unit -> int > > With stub generation as implemented in the git master branch the call > to 'foreign' changes slightly. Instead of calling 'foreign' just > once, we're going to call it once for each stage of generation. The > way we do this is to abstract over 'foreign' with a functor. (Note > the similarity to the original binding of 'f' above.) > > module Bindings (F : Cstubs.FOREIGN) = > struct > let f = F.foreign "foo" (void @-> returning int) > end > > The first application of the functor generates C: > > Cstubs.write_c std_formatter ~prefix:"foo_" (module Bindings) > > The output is a wrapper for the C function 'foo' that marshals and > unmarshals arguments and return values as needed. > > The second application generates OCaml: > > Cstubs.write_ml std_formatter ~prefix:"foo_" (module Bindings) > > The output is an OCaml module that we can pass to 'Bindings' for the > third and final application, which links together the declaration of > 'f' and the generated code: > > Bindings(Generated_ML) > > As with the dynamic binding, this gives us an OCaml function that we > can call without further ado: > > val f : unit -> int > > The build process is reasonably straightforward. Since we're > generating code, there are more steps than with the dynamic version, > but we're less likely to need obscure linker flags. A typical > approach is to place the bindings functor in one file -- > foo_binding.ml, say: > > module Bindings(F : Cstubs.FOREIGN) = > struct > let foo = F.foreign "foo" Ctypes.(void @-> returning int) > end > > and the calls to 'write_c' and 'write_ml' other files. I'll put the > call to 'write_c' along with code to print out the headers used in > generate_c.ml: > > let () = > print_endline "#include <ctypes/cstubs_internals.h>"; > print_endline "#include \"foo.h\""; > Cstubs.write_c Format.std_formatter ~prefix:"foo_" > (module Foo_binding.Bindings) > > The call to 'write_ml' goes in generate_ml.ml: > > let () = Cstubs.write_ml Format.std_formatter ~prefix:"foo_" > (module Foo_binding.Bindings) > > Then we can compile and run the two programs to generate the stub code: > > $ ocamlfind ocamlc -c -package ctypes.stubs \ > foo_binding.ml generate_c.ml generate_ml.ml > $ ocamlfind ocamlc -o generate_ml.native -linkpkg -package ctypes.stubs \ > foo_binding.cmo generate_ml.cmo > $ ./generate_ml.native > generated.ml > $ ocamlfind ocamlc -o generate_c.native -linkpkg -package ctypes.stubs \ > foo_binding.cmo generate_c.cmo > $ ./generate_c.native > generated_c_stubs.c > > We can then compile the stub code and link it in with the bindings > functor and the library containing 'foo': > > $ ocamlfind ocamlc -c -package ctypes.stubs -I `ocamlc -where`/.. \ > generated_c_stubs.c generated.ml > $ ocamlfind ocamlmklib -o foo -linkpkg -package ctypes.stubs \ > generated_c_stubs.o generated.cmo foo_binding.cmo -L. -lfoo > > Finally, we can load the code and call the 'foo' function: > > $ ocaml -short-paths > OCaml version 4.01.0 > > # #use "topfind";; > [...] > # #require "ctypes.stubs";; > [...] > # #load "foo.cma";; > # include Foo_binding.Bindings(Generated);; > val foo : unit -> int = <fun> > # foo ();; > foo called > - : int = 3 > > The full stub generation interface (which is actually just the > 'write_ml' and 'write_c' functions) is here: > > > https://github.com/ocamllabs/ocaml-ctypes/blob/1e1634/src/cstubs/cstubs.mli > > Jeremy > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa.inria.fr/sympa/arc/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > [-- Attachment #2: Type: text/html, Size: 8047 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Static linking via Ctypes? 2014-03-26 16:24 ` Travis Brady @ 2014-03-26 17:17 ` Daniel Bünzli 0 siblings, 0 replies; 12+ messages in thread From: Daniel Bünzli @ 2014-03-26 17:17 UTC (permalink / raw) To: Travis Brady Cc: Jeremy Yallop, Milan Stanojević, Dan Benjamin, David Sheets, Bruno Deferrari, O Caml Le mercredi, 26 mars 2014 à 17:24, Travis Brady a écrit : > So currently I can make binaries, but I'd love to be able to #require this in utop for interactive ipython-like usage. What's the error ? Isn't it maybe because the stublib isn't installed in whathever .opam/$SWITCH/lib/stublib ? If you didn't install yet you can try to make it look it up in your build dir by adding that directory to CAML_LD_LIBRARY_PATH, see: http://caml.inria.fr/pub/docs/manual-ocaml-4.01/runtime.html#sec256 Otherwise I'd suggest making it first working without oasis where you have control and understanding of what you do. You can then try to figure out later if you can retro fit what you have done in that cumbersome tool. Best, Daniel ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Static linking via Ctypes? 2014-03-25 23:14 ` Jeremy Yallop 2014-03-26 16:24 ` Travis Brady @ 2014-03-26 17:25 ` Milan Stanojević 1 sibling, 0 replies; 12+ messages in thread From: Milan Stanojević @ 2014-03-26 17:25 UTC (permalink / raw) To: Jeremy Yallop; +Cc: Dan Benjamin, David Sheets, Bruno Deferrari, O Caml Interesting. Thanks for the explanation. Just wanted to add that what David Sheets suggested worked for us (Jane Street) without need for any special linker flags apart from what our build system already does for C files which I think is pretty standard (compiles all C files into a library that is then linked into the packed ocaml library). But it's just one specific linux distribution On Tue, Mar 25, 2014 at 7:14 PM, Jeremy Yallop <yallop@gmail.com> wrote: > I wrote: >> Not exactly, since the stub generation support in the next ctypes >> release resolves these issues in a different way. In the current >> release (0.2.3) setting up foreign calls and linking are both entirely >> dynamic. Stub generation will make it possible to link statically as >> well. > > Milan Stanojević asked: >> Can you tell us how would this work exactly? >> Let's say I have a function "foo" in my C file (that I want to link >> statically) and I want to give use it in ocaml with a ctype (void @-> >> returning int) >> What would I need to say in my ocaml program and do I have to tell >> anything to my build system? > > With the current release of ctypes we'd bind 'foo' like this: > > let f = foreign "foo" (void @-> returning int) > > The 'foreign' function searches for the symbol "foo" and sets up the > call; the return value is an OCaml function that we can call > immediately. > > val f : unit -> int > > With stub generation as implemented in the git master branch the call > to 'foreign' changes slightly. Instead of calling 'foreign' just > once, we're going to call it once for each stage of generation. The > way we do this is to abstract over 'foreign' with a functor. (Note > the similarity to the original binding of 'f' above.) > > module Bindings (F : Cstubs.FOREIGN) = > struct > let f = F.foreign "foo" (void @-> returning int) > end > > The first application of the functor generates C: > > Cstubs.write_c std_formatter ~prefix:"foo_" (module Bindings) > > The output is a wrapper for the C function 'foo' that marshals and > unmarshals arguments and return values as needed. > > The second application generates OCaml: > > Cstubs.write_ml std_formatter ~prefix:"foo_" (module Bindings) > > The output is an OCaml module that we can pass to 'Bindings' for the > third and final application, which links together the declaration of > 'f' and the generated code: > > Bindings(Generated_ML) > > As with the dynamic binding, this gives us an OCaml function that we > can call without further ado: > > val f : unit -> int > > The build process is reasonably straightforward. Since we're > generating code, there are more steps than with the dynamic version, > but we're less likely to need obscure linker flags. A typical > approach is to place the bindings functor in one file -- > foo_binding.ml, say: > > module Bindings(F : Cstubs.FOREIGN) = > struct > let foo = F.foreign "foo" Ctypes.(void @-> returning int) > end > > and the calls to 'write_c' and 'write_ml' other files. I'll put the > call to 'write_c' along with code to print out the headers used in > generate_c.ml: > > let () = > print_endline "#include <ctypes/cstubs_internals.h>"; > print_endline "#include \"foo.h\""; > Cstubs.write_c Format.std_formatter ~prefix:"foo_" > (module Foo_binding.Bindings) > > The call to 'write_ml' goes in generate_ml.ml: > > let () = Cstubs.write_ml Format.std_formatter ~prefix:"foo_" > (module Foo_binding.Bindings) > > Then we can compile and run the two programs to generate the stub code: > > $ ocamlfind ocamlc -c -package ctypes.stubs \ > foo_binding.ml generate_c.ml generate_ml.ml > $ ocamlfind ocamlc -o generate_ml.native -linkpkg -package ctypes.stubs \ > foo_binding.cmo generate_ml.cmo > $ ./generate_ml.native > generated.ml > $ ocamlfind ocamlc -o generate_c.native -linkpkg -package ctypes.stubs \ > foo_binding.cmo generate_c.cmo > $ ./generate_c.native > generated_c_stubs.c > > We can then compile the stub code and link it in with the bindings > functor and the library containing 'foo': > > $ ocamlfind ocamlc -c -package ctypes.stubs -I `ocamlc -where`/.. \ > generated_c_stubs.c generated.ml > $ ocamlfind ocamlmklib -o foo -linkpkg -package ctypes.stubs \ > generated_c_stubs.o generated.cmo foo_binding.cmo -L. -lfoo > > Finally, we can load the code and call the 'foo' function: > > $ ocaml -short-paths > OCaml version 4.01.0 > > # #use "topfind";; > [...] > # #require "ctypes.stubs";; > [...] > # #load "foo.cma";; > # include Foo_binding.Bindings(Generated);; > val foo : unit -> int = <fun> > # foo ();; > foo called > - : int = 3 > > The full stub generation interface (which is actually just the > 'write_ml' and 'write_c' functions) is here: > > https://github.com/ocamllabs/ocaml-ctypes/blob/1e1634/src/cstubs/cstubs.mli > > Jeremy > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa.inria.fr/sympa/arc/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Caml-list] Static linking via Ctypes? 2014-03-25 14:54 [Caml-list] Static linking via Ctypes? dbenjamin 2014-03-25 15:04 ` Bruno Deferrari @ 2014-03-25 15:10 ` Daniel Bünzli 1 sibling, 0 replies; 12+ messages in thread From: Daniel Bünzli @ 2014-03-25 15:10 UTC (permalink / raw) To: dbenjamin; +Cc: caml-list Le mardi, 25 mars 2014 à 15:54, dbenjamin@janestreet.com a écrit : > I'm using Ctypes to interface with a dynamic library, but in addition to the > interface provided the library I have some helper functions (written in C, > against the same library) that I'd also like to call via Ctypes. Is there any > way to achieve this via static linking or am I required to build another > shared object? If you are using ctype's libffi backend you don't need in theory to build a shared dllmylib.so shared object to put in ocaml's lib/stublib. However in practice this is still useful to do even if that shared object is empty as it allows you to record the correct link flags for the dlled C library you bind to. Doing so allows your users to simply use the ocamlfind package or #require it in the toplevel and everything works correctly, no C link flags to mess with when the binding is used. This empty dll could be the place to put your helper functions. See this comment on how to proceed: https://github.com/ocamllabs/ocaml-ctypes/issues/51#issuecomment-30729675 e.g. in that case you would put your helper functions in that empty tsdl_stub.c file. Best, Daniel ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2014-03-26 17:26 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-03-25 14:54 [Caml-list] Static linking via Ctypes? dbenjamin 2014-03-25 15:04 ` Bruno Deferrari 2014-03-25 15:11 ` Dan Benjamin 2014-03-25 15:24 ` David Sheets 2014-03-25 17:55 ` Dan Benjamin 2014-03-25 21:19 ` Jeremy Yallop 2014-03-25 21:37 ` Milan Stanojević 2014-03-25 23:14 ` Jeremy Yallop 2014-03-26 16:24 ` Travis Brady 2014-03-26 17:17 ` Daniel Bünzli 2014-03-26 17:25 ` Milan Stanojević 2014-03-25 15:10 ` Daniel Bünzli
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox