Coder Social home page Coder Social logo

ocaml-ctypes's Introduction

ctypes is a library for binding to C libraries using pure OCaml. The primary aim is to make writing C extensions as straightforward as possible.

The core of ctypes is a set of combinators for describing the structure of C types -- numeric types, arrays, pointers, structs, unions and functions. You can use these combinators to describe the types of the functions that you want to call, then bind directly to those functions -- all without writing or generating any C!

GitHub Actions status

Usage

Suppose you want to bind to the following C functions:

   int sigemptyset(sigset_t *set);
   int sigfillset(sigset_t *set);
   int sigaddset(sigset_t *set, int signum);
   int sigdelset(sigset_t *set, int signum);
   int sigismember(const sigset_t *set, int signum);

Using ctypes you can describe the interfaces to these functions as follows:

   let sigemptyset = foreign "sigemptyset" (ptr sigset_t @-> returning int)
   let sigfillset = foreign "sigfillset" (ptr sigset_t @-> returning int)
   let sigaddset = foreign "sigaddset" (ptr sigset_t @-> int @-> returning int)
   let sigdelset = foreign "sigdelset" (ptr sigset_t @-> int @-> returning int)
   let sigismember = foreign "sigismember" (ptr sigset_t @-> int @-> returning int)

The names bound by this code have the types you might expect:

   val sigemptyset : sigset_t ptr -> int
   val sigfillset : sigset_t ptr -> int
   val sigaddset : sigset_t ptr -> int -> int
   val sigdelset : sigset_t ptr -> int -> int
   val sigismember : sigset_t ptr -> int -> int

That's all there is to it. Unlike the usual way of writing C extensions, there are no C "stub" functions to write, so there's much less opportunity for error.

The documentation and source distribution contain more complex examples, involving structs, unions, arrays, callback functions, and so on, and show how to create and use C values (like instances of sigset_t ptr) in OCaml.

Links

ocaml-ctypes's People

Contributors

aalekseyev avatar aantron avatar andrewray avatar artagnon avatar atupone avatar avsm avatar dannywillems avatar demimarie avatar dinosaure avatar dsheets avatar edwintorok avatar emillon avatar fdopen avatar glondu avatar lpw25 avatar maverickwoo avatar misterda avatar murmour avatar orbitz-other avatar rgrinberg avatar rleonid avatar robhoes avatar sadiqj avatar seliopou avatar smorimoto avatar talex5 avatar tiash avatar whitequark avatar yallop avatar ygrek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ocaml-ctypes's Issues

OCaml-Java backend

An OCaml-Java backend for ctypes would make it possible to write C bindings that work uniformly across OCaml and OCaml-Java.

Support for byte-aligned pointers

Pointers into the C heap are currently represented as immediate values, making it impossible to pass certain addresses between C and OCaml. We need some form of support for byte-aligned pointers, represented as custom/abstract values, either as the default or treated as a separate case.

Make threading support optional

Since #37, ctypes no longer passes OCaml functions to C, instead passing indexes into a table that contains the functions. Access to the table is guarded by a mutex, which introduces an unnecessary overhead in single-threaded applications. We should perhaps introduce a second implementation of the Identify_closure module and make it possible to select the appropriate implementation using Findlib's support for exactly this situation.

Enum support

Enum sizes are implementation-defined. We should expose the compiler/platform policy in order to make ctypes code platform-independent. Perhaps

   val enum : min:int -> max:int -> int type

is sufficient.

installation issue on MacOS X

Duplicated from realworldocaml/book#1323 by @Gtower1X:

running "brew install libffi" produces this: Warning: libffi-3.0.13 already installed. Then running "opam install ctypes" generates this:

The following recquired C libraries are missing: libffi.
Please install them and retry. If they are installed in a non-standard location
or need special flags, set the environment variables <LIB>_CFLAGS and <LIB>_LIBS
accordingly and retry.

For example, if libffi is installed in /opt/local, you can type:

export LIBFFI_CFLAGS=-I/opt/local/include
export LIBFFI_LIBS=-L/opt/local/lib

### stderr ###
E: Failure("Command 'ocaml discover.ml -ocamlc /Users/gregt/.opam/4.01.0dev+trunk/bin/ocamlc.opt -ext-obj .o -exec-name a.out' terminated with error code 1")
make: *** [setup.data] Error 1

Setting LIBFFI_LIBS to where libffi is installed (/usr/local/opt/libffi/lib) doesn't help.

-Wl,--no-as-needed support for Foreign

Some investigation reveals that there is no one combination that works out-of-the-box, since:

  • --no-as-needed is required on Ubuntu >=11.10
  • --no-as-needed is no longer recognized in MacOS X since >= Lion.

So a configure-time flag is mandatory. I'm wondering if embedding this directive in foreign.cma (via -cclib at configure-time) makes sense? The assumption is that every consumer of foreign.cma will need to force linking, so including the correct compiler option in Ctypes.Foreign makes sense.

I can cook up a patch if you think this sounds right...

(PS: also noticed that twitter/hadoop-lzo#34 has the same bug for their software)

How to get the value of a pointer?

Hi, every one:
I have a function in C:
void add( int a, int b, int *c) {
*c = a + b;
}

in ocaml:
let add3 = foreign ~from:lib "add3" ( int @-> int @-> ptr int @-> returning void );;
let c = allocate( ptr int); (* not work as intended, why? How? )
add3 3 4 c;; (
how ? *)
c;;

Thanks to anyone.
perlawk.

Type serialization support

Would it be reasonable to include a to_string function over types for both type references and type definitions?

I don't see this functionality in the library but it doesn't look like it would be terribly hard to implement. Have I missed something?

If I wrote up a patch to add this functionality, would you be interested in it?

Error message if `libffi` is not present

I get the following error if I do not have libffi present. Apparently @lpw25's error message is much more friendly and helpful :)

I'm on a Mac and using homebrew.

==== ERROR [while installing ctypes.0.1] ====
# opam-version    1.0.1
# os              darwin
# command         make
# path            /Users/amir/.opam/4.01.0dev+trunk/build/ctypes.0.1
# compiler        4.01.0dev+trunk
# exit-code       2
# env-file        /Users/amir/.opam/4.01.0dev+trunk/build/ctypes.0.1/ctypes-18112-ad8886.env
# stdout-file     /Users/amir/.opam/4.01.0dev+trunk/build/ctypes.0.1/ctypes-18112-ad8886.out
# stderr-file     /Users/amir/.opam/4.01.0dev+trunk/build/ctypes.0.1/ctypes-18112-ad8886.err
### stdout ###
oasis setup
ocaml setup.ml -configure --enable-tests
testing for brew: .............................. available
testing for pkg-config: ........................ available
testing for libffi:
### stderr ###
Exception: End_of_file.
E: Failure("Command 'ocaml discover.ml -ocamlc /Users/amir/.opam/4.01.0dev+trunk/bin/ocamlc.opt -ext-obj .o -exec-name a.out' terminated with error code 2")
make: *** [setup.data] Error 1

'opam install ctypes' failed.

Query C for struct and union layout.

The struct layout code is fragile, since structs in C interfaces may contain additional fields, or leave the order of fields unspecified. We might attack the problem by reading C headers to obtain the actual definition, although this is likely to be tricky where the preprocessor is involved. A better approach is to generate trivial C stubs that query the layout using offsetof and sizeof.

Generating C stubs still leaves us with a choice: the generated C code might be linked directly into the program, or we might run the C at configure time to generate OCaml code, then link the OCaml code in.

The issue also affects unions since additional members may increase the size and alignment requirements.

Issue #30 gives a crude sketch of stub generation; issue #15 is related; issues #48 and #54 are steps in approximately the right direction.

Thread support (releasing the runtime lock)

We need support for releasing the runtime (via caml_release_runtime_system / caml_acquire_runtime_system) while calling long-running functions. This is almost trivial, but we need to take care with callbacks.

redundant cclib in installed ctypes

An external usage of ctypes results in this warning every time

+ ocamlfind ocamlopt -linkpkg -package ctypes -package unix -cclib -lncurses ncurses.ml
ld: warning: directory not found for option '-Lsrc/'

which means that a cclib -Lsrc crept in the build system somewhere

no bool type

I found no single-bit type for boolean variables.
Is this a planned feature?

Static linking under OSX

Using OSX 10.8.3 with GCC 4.7.

I created a simply library using GCC, static linking with a C program works.

$ ocamlfind ocamlopt -cclib '-L. -lhello-static' -linkpkg -package ctypes.foreign demo.cmx -o demo.native 
$ ./demo.native
$ Fatal error: exception Dl.DL_error("dlsym(RTLD_DEFAULT, res): symbol not found")

I've seen some other issues with static linking here but most workarounds are linux-only as far as I can tell, or at least my linker doesn't support the proposed arguments.

Dynamic linking works fine.

memcpy

Expose something like memcpy so users don't have to do silliness like:

let sp = ref (p +@ (offsetof name_)) in
String.iter (fun c -> !sp <-@ c; sp := !sp +@ 1) name

Bigarray support

I know it's in the plans but I'd just like to mention that pretty much anything I'd like to do with C bindings actually involves bigarrays. So without support for it ocaml-ctypes is sadly useless for me.

Foreign.foreign give the ability to fail on use

In certain APIs it is useful to fail on usage rather than definition because actual platform support for a function call can be find out by other means and using the right functions should be left to the client (example: OpenGL extensions).

I propose to add an optional failuse flag to Foreign.foreign. See below for a prototype implementation, basically just wrap the existing implementation with an exception handler (that Obj.magic is due to the fact that the public ctypes API doesn't give a way to do anything useful with the result of Dl.dlsym, is that on purpose ?)

If there's interest I can turn that into a pull request. Tell me if you find a better name/signature.

let ptr_of_raw_ptr p = Ctypes.ptr_of_raw_address p

let foreign ?(failuse = false) ?from symbol typ = 
  try
    let open Ctypes in
    let p = ptr_of_raw_ptr (Obj.magic (dlsym ?handle:from ~symbol)) in
    let pp = to_voidp (allocate (ptr void) p) in
    !@ (from_voidp (funptr ~name:symbol typ) pp)
  with
  | exn -> if failuse then fun _ -> raise exn else raise exn 

(* test *)

let cos = foreign "cos" (double @-> (returning double)) 
let a_sin = foreign ~failuse:true "a_sin" (double @-> (returning double))

let () = 
  Printf.printf "%f\n" (cos 0.); 
  Printf.printf "%f\n" (a_sin 3.14) (* raises *)

Segmentation fault when using Ctypes with Async

Here is my ocaml session (run with an empty .ocamlinit):

$ ocaml
        OCaml version 4.01.0+dev18-2013-06-13

# #use "topfind";;
- : unit = ()
Findlib has been successfully loaded. Additional directives:
  #require "package";;      to load a package
  #list;;                   to list the available packages
  #camlp4o;;                to load camlp4 (standard syntax)
  #camlp4r;;                to load camlp4 (revised syntax)
  #predicates "p,q,...";;   to set these predicates
  Topfind.reset();;         to force that packages will be reloaded
  #thread;;                 to enable threads

- : unit = ()
# #thread;;
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ocaml/threads: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ocaml/unix.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ocaml/threads/threads.cma: loaded
# #require "async";;
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ocaml/bigarray.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ocaml/nums.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/num-top: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/num-top/num_top.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/num: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/sexplib: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/sexplib/sexplib.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/oUnit: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/oUnit/oUnit.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/pa_ounit: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/pa_ounit/pa_ounit_lib.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/fieldslib: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/fieldslib/fieldslib.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/bin_prot: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/bin_prot/bin_prot.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/variantslib: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/variantslib/variantslib.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/res: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/res/res.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/core_kernel: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/core_kernel/core_kernel.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/core: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/core/core.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/core/core_top.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/async_core: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/async_core/async_core.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/comparelib: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/comparelib/comparelib.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/async_unix: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/async_unix/async_unix.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/async_extra: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/async_extra/async_extra.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/async: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/async/async.cma: loaded
# #require "ctypes.foreign";;
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ctypes: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ctypes/ctypes.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ctypes/ctypes-foreign.cma: loaded
# open Ctypes;;
# open PosixTypes;;
# open Foreign;;
# let time = foreign "time" (ptr time_t @-> returning time_t);;
Segmentation fault (core dumped)

If #require "async" is skipped above, everything seems to work fine:

$ ocaml
        OCaml version 4.01.0+dev18-2013-06-13

# #use "topfind";;
- : unit = ()
Findlib has been successfully loaded. Additional directives:
  #require "package";;      to load a package
  #list;;                   to list the available packages
  #camlp4o;;                to load camlp4 (standard syntax)
  #camlp4r;;                to load camlp4 (revised syntax)
  #predicates "p,q,...";;   to set these predicates
  Topfind.reset();;         to force that packages will be reloaded
  #thread;;                 to enable threads

- : unit = ()
# #thread;;
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ocaml/threads: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ocaml/unix.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ocaml/threads/threads.cma: loaded
# #require "ctypes.foreign";;
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ctypes: added to search path
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ctypes/ctypes.cma: loaded
/home/manzyuk/.opam/4.01.0dev+trunk/lib/ctypes/ctypes-foreign.cma: loaded
# open Ctypes;;
# open PosixTypes;;
# open Foreign;;
# let time = foreign "time" (ptr time_t @-> returning time_t);;
val time : PosixTypes.time_t Ctypes.ptr -> PosixTypes.time_t = <fun>

However, requiring "async" immediately afterwards causes a segmentation fault again.

I'm running Ctypes 0.1 on Ubuntu:

$ opam list --installed | grep ctypes
ctypes                     0.1  Combinators for binding to C libraries without writing any C.
$ uname -a
Linux paddy 3.5.0-36-generic #57~precise1-Ubuntu SMP Thu Jun 20 15:22:35 UTC 2013 i686 i686 i386 GNU/Linux

I'd be happy to provide more information on my system if that would help to chase down this bug.

Using local version of `libffi` instead of homebrew version

I'm trying to build @dsheets' signpost repo (which depends on dnscurve, which depends on sodium, which depends on ctypes).

I get an error during build and I've copied the latter part of the _log file below, which indicates this is related to ctypes.

+ ocamlfind ocamlopt -g -w @f@p@u -linkpkg -package cmdliner -package dns -package dnscurve -package dnscurve.lwt -package lwt.unix -package sodium src/signpost.cmxa src/ace/ace.cmxa src/ace/spaced.cmx -o src/ace/spaced.native
Undefined symbols for architecture x86_64:
  "_ffi_closure_alloc", referenced from:
      _ctypes_make_function_pointer in libctypes_stubs.a(ctypes_stubs.o)
  "_ffi_prep_closure_loc", referenced from:
      _ctypes_make_function_pointer in libctypes_stubs.a(ctypes_stubs.o)
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
File "caml_startup", line 1:
Error: Error during linking
Command exited with code 2.
# Compilation unsuccessful.

Comment from @avsm via email:

This looks like the wrong version of libffi was picked up on MacOS X (the built-in version is too old).

Ctypes should (in theory) reject the older libffi in favour of one installed via Homebrew (and installed in /usr/local/Cellar/<...>). This doesn't seem to have happened in this case for some reason.

Is there something I can do to get you a more useful output to debug this?

System details

  • Mac OSX 10.8.4
  • homebrew version 0.9.4
  • libffi: stable 3.0.13 - via homebrew at /usr/local/Cellar/libffi/3.0.13

string_opt ?

I have a C function that can return a possibly NULL value of type const *char. Is there a quick way of expressing that (don't want to rewrite the view for strings) ?

SIGSEGV on string/ptr char coercion through ptr void

open Ctypes
open Foreign

;;
let str = "15 char string!" in
let char_ptr = coerce string (ptr char) str in
let late_str = !@ (from_voidp string (to_voidp char_ptr)) in
(*let late_str = coerce (ptr char) string (char_ptr +@ 12) in*)
Printf.printf "%s\n%!" late_str

Kaboom!

Am I missing something?

build failed on Debian Squeeze

I've tried to install ctypes on Debian Squeeze with opam 1.1. Build fails with the following:

===== ERROR while installing ctypes.0.1.1 =====
# opam-version 1.1.0
# os           linux
# command      make
# path         /home/crox/.opam/4.01.0/build/ctypes.0.1.1
# compiler     4.01.0
# exit-code    2
# env-file     /home/crox/.opam/4.01.0/build/ctypes.0.1.1/ctypes-16724-d2d111.env
# stdout-file  /home/crox/.opam/4.01.0/build/ctypes.0.1.1/ctypes-16724-d2d111.out
# stderr-file  /home/crox/.opam/4.01.0/build/ctypes.0.1.1/ctypes-16724-d2d111.err
### stdout ###
# ...[truncated]
# + ocamlfind ocamlc -ccopt -fPIC -ccopt -Wall -ccopt -Wno-unused-variable -ccopt -g -c src/posix_types_stubs.c
# src/posix_types_stubs.c: In function ‘ctypes_typeof_blksize_t’:
# src/posix_types_stubs.c:69: error: ‘blksize_t’ undeclared (first use in this function)
# src/posix_types_stubs.c:69: error: (Each undeclared identifier is reported only once
# src/posix_types_stubs.c:69: error: for each function it appears in.)
# src/posix_types_stubs.c:69: error: expected ‘)’ before numeric constant
# src/posix_types_stubs.c: In function ‘ctypes_typeof_clock_t’:
# src/posix_types_stubs.c:70: error: ‘clock_t’ undeclared (first use in this function)
# src/posix_types_stubs.c:70: error: expected ‘)’ before numeric constant
# Command exited with code 2.
### stderr ###

$ gcc --version
gcc (Debian 4.4.5-8) 4.4.5

The ncurses example doesn't work for me

This is the error that I get when I run ncurses_cmd.native:

Fatal error: exception Dl.DL_error("/home/rudi/reps/ocaml-ctypes/ncurses_cmd.native: undefined symbol: initscr")

I run the most recent version of ubuntu and have installed all the ncurses packages I could find.

lib32ncurses5                                   5.9-10ubuntu4 
lib32ncurses5-dev                               5.9-10ubuntu4 
lib32ncursesw5                                  5.9-10ubuntu4 
lib32ncursesw5-dev                              5.9-10ubuntu4 
libcurses-ocaml                                 1.0.3-2       
libncurses5:amd64                               5.9-10ubuntu4 
libncurses5:i386                                5.9-10ubuntu4 
libncurses5-dev                                 5.9-10ubuntu4 
libncursesw5:amd64                              5.9-10ubuntu4 
libncursesw5:i386                               5.9-10ubuntu4 
libncursesw5-dev                                5.9-10ubuntu4 
libx32ncurses5                                  5.9-10ubuntu4 
libx32ncurses5-dev                              5.9-10ubuntu4 
libx32ncursesw5                                 5.9-10ubuntu4 
libx32ncursesw5-dev                             5.9-10ubuntu4 
ncurses-base                                    5.9-10ubuntu4 
ncurses-bin                                     5.9-10ubuntu4 
ncurses-examples                                5.9-10ubuntu4 

Static linking ?

This library is really scary (because it feels like magic).

One question though. It doesn't work if you statically link the C library you bind to or I am missing something ?

(osx)

Static:

/Users/dbuenzli/.opam/4.00.1/bin/ocamlfind ocamlopt -linkpkg -g -cclib /usr/local/lib/libSDL2.a -package ctypes -package ctypes.foreign src/sdl.cmx src/omin.cmx -o src/omin.native
> otool -L omin.native 
omin.native:
    /usr/local/opt/libffi/lib/libffi.6.dylib (compatibility version 7.0.0, current version 7.1.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
> ./omin.native 
Fatal error: exception Dl.DL_error("dlsym(RTLD_DEFAULT, SDL_Init): symbol not found")
Raised at file "src/dl.ml", line 42, characters 26-44
Called from file "src/foreign.ml", line 18, characters 25-53
Called from file "src/sdl.ml", line 15, characters 11-63

Dynamic:

/Users/dbuenzli/.opam/4.00.1/bin/ocamlfind ocamlopt -linkpkg -g -cclib -L/usr/local/lib -cclib -lSDL2 -package ctypes -package ctypes.foreign src/sdl.cmx src/omin.cmx -o src/omin.native
> otool -L omin.native 
omin.native:
    /usr/local/opt/libffi/lib/libffi.6.dylib (compatibility version 7.0.0, current version 7.1.0)
    /usr/local/lib/libSDL2-2.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
> ./omin.native 

(works)

generate C stub code from fn/typ values

One useful addition would be a command-line IDL generator to generate static C stubs and the matching external mli signature file from a fn/typ type description.

This would permit the C output to be statically linked rather than dynamically opened, and would completely sidestep the dependency on libffi2.

Missing Unsigned.UInt32.{of,to}_int32

Semantically implemented as "%identity". Allows to write your unsigned 32 bits constants has hex in OCaml code (e.g. let mask = Unsigned.UInt32.of_int32 0xF000000l).

Generated ctypes.cmxs is useless

ctypes.cmxs is generated from ctypes.cmx and hence does not include the C stubs.

ctypes.cmxs should be generated from ctypes.cmxa instead.

Installation on Windows/mingw

Is there any way to install ocaml-ctypes without OPAM which does'nt compile on Windows ?
Is it possible to just compile ocaml-ctypes with ocamlbuild ?
I would like to compile and try ocaml-ctypes on windows with ocaml/mingw : I'm using in cygwin the mingw cross-compiler (i686-w64-mingw32-gcc).

Lifetime of functions passed to C

Passing OCaml functions to C functions involves storing a reference to the function value in an ffi_closure structure. We currently store a pointer to the value itself, but there's a potential bug here: GC could invalidate the pointer before the function is called. We currently avoid this by registering callbacks as global roots, but this is unsatisfactory, since there's no general safe time to unregister the roots.

Instead of storing a pointer to the OCaml function we should store an index into a weak table and put the responsibility for keeping callbacks alive on the calling program. Bindings written using ctypes can then ensure that functions passed to C stay around for as long as they are accessible from C. (For example, the comparison function passed to fts_open needs the same lifetime as the FTS structure, which is easily achieved by using a pair of both values to represent the FTS type on the OCaml side).

separate out dlsym from types library

Suggesting this before the first release as it's an interface-breaking change.

Can we have the Types library as a separate findlib package from the libffi foreign bindings?

This makes it easier to separate the concerns of constructing the C descriptions (e.g. via CIL or cstruct) and generating the foreign calls (initially via libffi, but potentially also via an IDL C generator or a specialised linker for Mirage/Xen kernels).

posix stubs break on macos x

+ ocamlfind ocamlc -ccopt -fPIC -ccopt -Wall -ccopt -Wno-unused-variable -ccopt -g -ccopt -I/usr/local/Cellar/libffi/3.0.13/lib/libffi-3.0.13/include -c src/posix_types_stubs.c
src/posix_types_stubs.c: In function ‘ctypes_typeof_clockid_t’:
src/posix_types_stubs.c:67: error: ‘clockid_t’ undeclared (first use in this function)
src/posix_types_stubs.c:67: error: (Each undeclared identifier is reported only once
src/posix_types_stubs.c:67: error: for each function it appears in.)
src/posix_types_stubs.c:67: error: expected ‘)’ before numeric constant
src/posix_types_stubs.c: In function ‘ctypes_typeof_pthread_t’:
src/posix_types_stubs.c:78: error: cannot convert to a pointer type
src/posix_types_stubs.c:78: warning: comparison between pointer and integer
src/posix_types_stubs.c: In function ‘ctypes_sizeof_timer_t’:
src/posix_types_stubs.c:98: error: ‘timer_t’ undeclared (first use in this function)
src/posix_types_stubs.c:98: warning: control reaches end of non-void function
Command exited with code 2.

This looks like...

  • clockid_t just isn't present on MacOS X
  • pthread_t has an opaque integer type isnt it? Can't convert to a pointer safely anywhere
  • timer_t also isn't present on MacOS X

CIL to Ctypes interface

Just keeping this issue to remind myself that I started working on a simple CIL -> Ctypes transformer that got this far in 10 minutes:

$ opam install cil
$ gcc -E /usr/include/ncurses.h > tmp.h
# utop
# require "cil";;
let f = Frontc.parse "tmp.h" () in
let print_typ typ = Pretty.sprint ~width:50 (Cil.d_type () typ) in
Cil.(iterGlobals f (function |GVarDecl(
    {vname; vtype=TFun(rty,Some attr,_,_)},_) -> 
        Printf.printf "%s (%s) -> %s\n" vname 
            (String.concat ", " (List.map (fun (_,ty,_) ->
                print_typ ty) attr)) (print_typ rty) |_ -> () ));;

which outputs from the C header file:

use_screen (SCREEN *, int (*)(SCREEN * , void * ), void *) -> int 
use_window (WINDOW *, int (*)(WINDOW * , void * ), void *) -> int 
wresize (WINDOW *, int , int ) -> int 
nofilter () -> void 
wgetparent (WINDOW const   *) -> WINDOW *
is_cleared (WINDOW const   *) -> _Bool 
is_idcok (WINDOW const   *) -> _Bool 
is_idlok (WINDOW const   *) -> _Bool 
is_immedok (WINDOW const   *) -> _Bool 

A bit more work and that could turn into a Ctypes call, and we could have a camlp4 extension that lets you write "#include <ncurses.h>" and automatically import in type-safe OCaml calls. A ppx equivalent should also be straightforward with an extension_point.

Toplevel, how to dynlink the C library ?

Now that I figured out how static linking works. How do we proceed for the toplevel (without making a custom toplevel of course) ?

So I produce my .cma with my ctypes foreign calls but I first need to link the dynamic C library when I try to load my .cma in the toplevel. --dllib when producing the .cma won't work as it enforces a naming convention on you (I'm tempted about trying symlink tricks but...) and the -cclib -lMylib you mention when you produce the .cma doesn't seem to be looked up by the toplevel.

Any hint ?

Efficient `string` creation from `char ptr` and `int`

I couldn't find an easy way to create an OCaml-level string given a char ptr and an int. The coercion from char ptr to string is based on the C convention of null-terminated strings, which doesn't work very well with binary data. It'd be useful to have such function available.

This might be somewhat related to #92.

undefined symbol: readline

I'm probably missing something obvious, but I couldn't figure out how to use Ctypes to define a function calling out to GNU Readline's readline function:

let read_line = foreign "readline" (string @-> returning (ptr string));;
Exception:
Dl.DL_error
 "/home/phil/.opam/4.01.0dev+trunk/lib/stublibs/dllctypes-foreign_stubs.so: undefined symbol: readline".

full toplevel transcript

This is from ctypes 0.1.1 with OCaml 4.01.0+dev18-2013-06-13 on Debian stable. I've confirmed both libffi5 and libreadline6 are installed. Any idea what's going on?

Improved treatment of coercions

Coercions between different types are a cornerstone of C, but currently rather awkward in ctypes. The main way to coerce a value from type s to type d at the moment is to coerce its address from s* to void* to d*, which is clunky, inefficient and insufficiently general (since it's just representation reinterpretation rather than value transformation.)

It'd be nice to have a more general and principled approach to coercions, perhaps based around a set of values that witness coercability. We might like to distinguish lossy coercions such as float to int from lossless coercions such as char to long, and safe coercions such as int* to void* from unsafe coercions such as void* to int*.

Endianness Support

Support for Big Endian, Little Endian, and Host Endian layouts would bring ctypes into feature parity on primitive types with cstruct.

Is there currently endianness support somehow?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.