3

I want to use the cFromEnum function, but this resides in the C2HS module, which I'm told is unnecessary and shouldn't be unpacked / installed ( c2hs not getting installed / registered correctly ). What's the modern way to convert an enum? For concreteness, here's my code.

{# enum BNType {underscoreToCase} deriving (Show, Eq) #}
{# pointer *NodeVector newtype #}
{# fun get_nodes_by_type { cFromEnum `BNType' } -> `NodeVector' id #}

(get_nodes_by_type will eventually take an argument; I'm just trying to get something working for now).

Community
  • 1
  • 1
gatoatigrado
  • 16,580
  • 18
  • 81
  • 143

1 Answers1

1

AFAICT, at this point c2hs users are left writing their own marshalling functions. Unfortunately marshallers have to be names, not arbitrary expressions, so you can't use fromIntegral . fromEnum as a marshaller within a c2hs declaration.

Presently I write marshallers myself and include them in the .c2hs file. Here are some marshallers from one of my more complicated bindings. I find the situation for withObject particularly galling, but not so much so that I've attempted to fix it myself yet.

cIntToEnum :: Enum a => CInt -> a
cIntToEnum = toEnum . fromIntegral

cIntFromEnum :: Enum a => a -> CInt
cIntFromEnum = fromIntegral . fromEnum

cIntConv :: (Integral a, Num b) => a -> b
cIntConv = fromIntegral

cFloatConv :: (Real a, Fractional b) => a -> b
cFloatConv = realToFrac

-- |since c2hs doesn't allow "with" as an input marshaller,
-- withObject is a synonym.
withObject :: Storable a => a -> (Ptr a -> IO b) -> IO b
withObject = with

withFloatArray :: (Storable b, RealFloat b, RealFloat a) =>
  [a]
  -> (Ptr b -> IO b1)
  -> IO b1
withFloatArray = withArray . map (cFloatConv)

Arguably, many of these should be extracted and put into a common library. If it were bundled with the c2hs package, that would be perfect (IMHO the C2HS module was removed a bit prematurely).

John L
  • 27,937
  • 4
  • 73
  • 88