{"action":"created","issue":{"url":"https://api.github.com/repos/ocamllabs/ocaml-ctypes/issues/320","labels_url":"https://api.github.com/repos/ocamllabs/ocaml-ctypes/issues/320/labels{/name}","comments_url":"https://api.github.com/repos/ocamllabs/ocaml-ctypes/issues/320/comments","events_url":"https://api.github.com/repos/ocamllabs/ocaml-ctypes/issues/320/events","html_url":"https://github.com/ocamllabs/ocaml-ctypes/issues/320","id":97284128,"number":320,"title":"Add optional function declaration in write_c","user":{"login":"rleonid","id":6570317,"avatar_url":"https://avatars.githubusercontent.com/u/6570317?v=3","gravatar_id":"","url":"https://api.github.com/users/rleonid","html_url":"https://github.com/rleonid","followers_url":"https://api.github.com/users/rleonid/followers","following_url":"https://api.github.com/users/rleonid/following{/other_user}","gists_url":"https://api.github.com/users/rleonid/gists{/gist_id}","starred_url":"https://api.github.com/users/rleonid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rleonid/subscriptions","organizations_url":"https://api.github.com/users/rleonid/orgs","repos_url":"https://api.github.com/users/rleonid/repos","events_url":"https://api.github.com/users/rleonid/events{/privacy}","received_events_url":"https://api.github.com/users/rleonid/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-07-26T04:13:50Z","updated_at":"2015-07-27T13:19:29Z","closed_at":null,"body":"In lieu of including a specific header file (such as the case if there isn't one because you're writing the code, for example) before writing out the stub code with `Cstubs.write_c` it could be useful to have `write_c` write out all the function declarations to avoid `-Wimplicit-function-declaration` warnings.\r\n\r\nWould this be a useful feature?"},"comment":{"url":"https://api.github.com/repos/ocamllabs/ocaml-ctypes/issues/comments/125201760","html_url":"https://github.com/ocamllabs/ocaml-ctypes/issues/320#issuecomment-125201760","issue_url":"https://api.github.com/repos/ocamllabs/ocaml-ctypes/issues/320","id":125201760,"user":{"login":"yallop","id":1736496,"avatar_url":"https://avatars.githubusercontent.com/u/1736496?v=3","gravatar_id":"","url":"https://api.github.com/users/yallop","html_url":"https://github.com/yallop","followers_url":"https://api.github.com/users/yallop/followers","following_url":"https://api.github.com/users/yallop/following{/other_user}","gists_url":"https://api.github.com/users/yallop/gists{/gist_id}","starred_url":"https://api.github.com/users/yallop/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yallop/subscriptions","organizations_url":"https://api.github.com/users/yallop/orgs","repos_url":"https://api.github.com/users/yallop/repos","events_url":"https://api.github.com/users/yallop/events{/privacy}","received_events_url":"https://api.github.com/users/yallop/received_events","type":"User","site_admin":false},"created_at":"2015-07-27T13:19:29Z","updated_at":"2015-07-27T13:19:29Z","body":"This is actually already possible with the existing public API, using the [Cstubs_inverted.write_c_header][write_c_header] function.  The implementation involves a small amount of glue, since bindings are usually written as a functor of type [Cstubs.BINDINGS][cstubs_bindings], but `write_c_header` expects a functor of type [Cstubs_inverted.BINDINGS][cstubs_inverted_bindings].\r\n\r\nHere's the glue, in the form of a (higher-order) functor `Invert`, which converts a `Cstubs.BINDINGS` functor to a `Cstubs_inverted.BINDINGS` functor:\r\n\r\n```ocaml\r\nmodule Invert (B: Cstubs.BINDINGS) (I: Cstubs_inverted.INTERNAL) =\r\n  struct\r\n    module Ignored =\r\n      B(struct\r\n        type 'a fn = unit\r\n        let foreign name fn = I.internal name fn (fun _ -> assert false)\r\n        let foreign_value _ = failwith \"foreign_value not supported\"\r\n      end)\r\n  end\r\n```\r\n\r\n`Invert` makes it possible to write a function `write_declarations` which writes out declarations corresponding to a bindings functor: \r\n\r\n```ocaml\r\nlet write_declarations fmt (module B : Cstubs.BINDINGS) =\r\n  Cstubs_inverted.write_c_header fmt ~prefix:\"\" (module Invert(B))\r\n```\r\n\r\nHere are some example bindings:\r\n\r\n```ocaml\r\nmodule Bindings(F: Cstubs.FOREIGN) =\r\nstruct\r\n  let sqrt = F.foreign \"sqrt\" (double @-> returning double)\r\n  let puts = F.foreign \"puts\" (string @-> returning int)\r\nend\r\n```\r\n\r\nNow we can pass `Bindings` to the usual functions, such as [Cstubs_write_c][write_c] to generate stubs:\r\n\r\n```\r\n# Cstubs.write_c Format.std_formatter ~prefix:\"\" (module Bindings);;\r\n#include \"ctypes_cstubs_internals.h\"\r\n\r\nvalue _1_sqrt(value x9)\r\n{\r\n   double x10 = Double_val(x9);\r\n   double x13 = sqrt(x10);\r\n   return caml_copy_double(x13);\r\n}\r\nvalue _2_puts(value x14)\r\n{\r\n   char* x15 = CTYPES_ADDR_OF_FATPTR(x14);\r\n   int x16 = puts(x15);\r\n   return Val_int(x16);\r\n}\r\n- : unit = ()\r\n```\r\n\r\nor to the `write_declarations` function above to generate declarations:\r\n\r\n```\r\n# write_declarations Format.std_formatter (module Bindings);;\r\ndouble sqrt(double x17);\r\nint puts(char* x18);\r\n\r\n- : unit = ()\r\n```\r\n\r\n\r\n[write_c_header]: https://github.com/ocamllabs/ocaml-ctypes/blob/495e2458f37824175d53b7794a0dd56e576e98ca/src/cstubs/cstubs_inverted.mli#L34\r\n[cstubs_bindings]: https://github.com/ocamllabs/ocaml-ctypes/blob/495e2458f37824175d53b7794a0dd56e576e98ca/src/cstubs/cstubs.mli#L79\r\n[cstubs_inverted_bindings]: https://github.com/ocamllabs/ocaml-ctypes/blob/495e2458f37824175d53b7794a0dd56e576e98ca/src/cstubs/cstubs_inverted.mli#L23\r\n[write_c]: https://github.com/ocamllabs/ocaml-ctypes/blob/495e2458f37824175d53b7794a0dd56e576e98ca/src/cstubs/cstubs.mli#L81\r\n"}}