Search code examples
haskellffic2hs

What's the modern way to access C2HS marshalling functions?


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


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