Question

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).

Was it helpful?

Solution

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).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top