haskell / c2hs

c2hs is a pre-processor for Haskell FFI bindings to C libraries
http://hackage.haskell.org/package/c2hs
Other
199 stars 50 forks source link

{#const #} doesn't really work for #define constants #200

Open dpreed opened 6 years ago

dpreed commented 6 years ago

The current implementation of the const hook is disappointing. Essentially it is a string replacement only for a define, so it doesn't do a reasonable thing with any kind of expressions. The macro definition, post-expansion by the C preprocessor, is what is inserted.

#include <errno.h>                                                                                                                      
einval = {#const EINVAL #}

#include <linux/kvm.h>                                                                                                                  
kvmGetMpState = {#const KVM_GET_MP_STATE #}

gets converted to:

einval = 22

kvmGetMpState = 2u << 0 + 8 + 8 + 14 | 0xae << 0 + 8 | 0x98 << 0 | sizeof(struct kvm_mp_state) << 0 + 8 + 8

where the second line is hardly what one would expect when reading the documentation for #const I would rename {#const} to {#define #} if its implementation remains as it is, since it is not a constant that is imported, but the string of the define. That's slightly useful, but only slightly.

There are two issues to deal with if one wants to deal with C #define constants better.

1) get the C type and convert it to a Haskell expression of the correct Haskell C type. 2) Calculate the value correctly.

The latter can be done by using GCC or Clang, including the include file into a constructed C file, compiling it, and running it, such that it prints out the attributes of the C constants. Getting the C type and the Haskell type can be done several ways.

An ideal design would be to extend {#const foo #} to be {#const foo[ctype] `hsty' #} where ctype is the c type of the value and hsty is the Haskell type. The []'s correspond to the notation in the variadic #fun syntax - the C type to cast the result to.

Is this a reasonable idea?

In any case, my short term need is to translate #define's that use the _IOR macros that define ioctl constants, which produce relatively useless expressions.

vmchale commented 5 years ago

The latter can be done by using GCC or Clang, including the include file into a constructed C file, compiling it, and running it, such that it prints out the attributes of the C constants.

Well, this would cause problems with cross-compilation.

However, I would definitely appreciate this feature.