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

Query C for struct layout #62

Merged
merged 4 commits into from
Oct 27, 2014
Merged

Query C for struct layout #62

merged 4 commits into from
Oct 27, 2014

Conversation

yallop
Copy link
Owner

@yallop yallop commented Aug 14, 2013

What's this?

A new module, Cstubs_structs, that supports retrieving the layout of structs and unions from C declarations.

What problem does it solve?

The current structure description API computes the layout of the structs and unions you describe in your program. This works well in simple cases if you're careful, but there's no check that what you write matches the declared type, and some cases are tricky to handle. For example, there's currently no clear solution for when

  • The C library uses compiler directives such as [#pragma pack][pragma-pack] to change the field layout algorithm
  • The layout of a struct differs between versions of a library
  • The set of fields in a struct changes according to platform

How does this change solve the problem?

The new module generates C code that is compiled against the header to retrieve the struct layout information from the C compiler, guaranteeing that the layout of structs used in your OCaml/ctypes program matches the layout in the C library you're binding.

How do I use it?

The interface is very similar to the existing structure description API, and in most cases it should be easy to switch. Let's consider an example. Here's a simple C struct declaration:

struct cell
{
  int payload;
  struct cell *next;
};

You can describe this struct using the existing API as follows:

let cell    = structure "cell"
let payload = field cell int "payload"
let next    = field cell (ptr cell) "next"
let ()      = seal cell

With the Cstubs_structs module in this pull request you put the declaration inside a functor:

module Bindings(S : Cstubs_structs.STRUCT) =
struct
  open S
  let cell    = structure "cell"
  let payload = field cell int "payload"
  let next    = field cell (ptr cell) "next"
  let ()      = seal cell
end

and then pass the functor to generate a C program:

Cstubs_structs.write_c formatter (module Bindings)

The C program then an ML module which you can link in to your program:

include Bindings(Generated_module) 

Isn't the build process rather complex?

Perhaps, but each step has a clear rationale. Generating C is the best way to retrieve information from library headers. Having the C program then generate an ML program makes it possible to inline the retrieved layout information into your program. Using a functor to link the generator and the generated code together makes it possible to give strong guarantees about typing.

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

Successfully merging this pull request may close these issues.

1 participant