haskell / c2hs

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

{#const #} doesn't work for `enum`, only `#define` #154

Open mtolly opened 8 years ago

mtolly commented 8 years ago

The const feature introduced in #65 isn't working for me; it's simply inserting the C constant name, not its actual defined value.

SndfileExtra.chs:

module SndfileExtra where

import Foreign
import Foreign.C

#include <sndfile.h>

setVBREncodingQuality :: CInt
setVBREncodingQuality = {#const SFC_SET_VBR_ENCODING_QUALITY #}

After c2hs SndfileExtra.chs, SndfileExtra.hs:

-- GENERATED by C->Haskell Compiler, version 0.27.1 Eternal Sunshine, 29 November 2015 (Haskell)
-- Edit the ORIGNAL .chs file instead!

{-# LINE 1 "SndfileExtra.chs" #-}
module SndfileExtra where

import Foreign
import Foreign.C

setVBREncodingQuality :: CInt
setVBREncodingQuality = SFC_SET_VBR_ENCODING_QUALITY
{-# LINE 9 "SndfileExtra.chs" #-}

Which of course leads to a GHC error that SFC_SET_VBR_ENCODING_QUALITY isn't defined.

(Also, I'm just now noticing the typo in ORIGNAL.)

ian-ross commented 8 years ago

@mtolly This is because {#const ...#} only works for constants defined using #define, not for enum values (which is what SFC_SET_VBR_ENCODING_QUALITY is). That's obviously not very helpful, so let me see if I can work out how to make it more useful!

mtolly commented 8 years ago

Ahh! That's totally my mistake; I wasn't even thinking about the difference between those. Feel free to change it or not; I'm already using an {#enum define for it so I'm good either way.

I suppose the reason to support enums would be that often the documentation for a library doesn't distinguish between the two methods -- the relevant libsndfile page just says:

The cmd parameter is an integer identifier which is defined in <sndfile.h>.
All of the valid command identifiers have names beginning with "SFC_".

So one would have to look in the actual header file to see how it's defined. (And, in theory it could even change from version to version.) I guess this is another version of the issue between writing a binding to a function versus a macro.