Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow passing OCaml values directly to stubs #569

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

aantron
Copy link
Contributor

@aantron aantron commented May 23, 2018

I want to call

void get_sockaddr(value mladr,
                  union sock_addr_union * adr /*out*/,
                  socklen_param_type * adr_len /*out*/);

...but I found no way to pass the value argument in current ctypes.

So, this PR adds:

val ocaml_any_value : 'a typ
(** Value representing any OCaml value, to be accessed from C directly. This
    corresponds to the C type [value] from [caml/mlvalues.h]. *)

...which is used like this:

(* type t defined elsewhere *)
let unix_sockaddr : Unix.sockaddr typ = ocaml_any_value

let get =
  foreign "get_sockaddr"
    (unix_sockaddr @-> ptr t @-> ptr int @-> returning void)

The ML code generated for get is:

external luv_stub_63_get_sockaddr : 'a -> _ CI.fatptr -> _ CI.fatptr -> unit
  = "luv_stub_63_get_sockaddr"

(* ... *)

| Function
    (CI.OCaml_value,
     Function (CI.Pointer _, Function (CI.Pointer _, Returns CI.Void))),
  "get_sockaddr" ->
  (fun x13 x14 x15 ->
    luv_stub_63_get_sockaddr x13 (CI.cptr x14) (CI.cptr x15))

...and the C stub is:

value luv_stub_63_get_sockaddr(value x270, value x269, value x268)
{
   union sock_addr_union* x272 = CTYPES_ADDR_OF_FATPTR(x269);
   int* x273 = CTYPES_ADDR_OF_FATPTR(x268);
   get_sockaddr(x270, x272, x273);
   return Val_unit;
}

These look right to me, and seem to work. I'm not sure about some of the other code this PR touches, like in cstubs_analysis.ml.

@yallop
Copy link
Owner

yallop commented Jul 2, 2018

I understand the aim of this PR, but passing OCaml values to C can be quite subtle, and it's rarely needed, so I think the cost/benefit balance is against adding this feature.

@aantron
Copy link
Contributor Author

aantron commented Jul 24, 2018

This tends to be useful also for calling the runtime's Bigarray helpers. I find it very helpful for developing https://github.com/aantron/luv. I guess without this PR, I would have to use regular external declarations, which I'm trying to minimize.

@bobot
Copy link
Contributor

bobot commented Jan 11, 2022

It would simplify a lot #643, where one wants to communicate between two stubs, one being [zarith.h] (https://github.com/ocaml/Zarith/blob/master/zarith.h). I believe it is useful for any stubs that provide conversion function from the C type to/from the OCaml type.

I tried to add the feature on the current master just as Obj.t typ for simplicity (views should allow to generalize it), with a test at https://github.com/bobot/ocaml-ctypes/tree/obj_t_typ. It works with stubs but not with foreign even if there are fixes compared to this MR on the handling of those values as argument and result. (EDIT: the error is fixed, the example works)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants