-
Notifications
You must be signed in to change notification settings - Fork 52
Closed
Labels
Description
Currently, C's char types can be marshalled to and from Integral types via the default marshaller fromIntegral. Unfortunately, this makes it difficult to use Haskell's own Char type alongside C's, since Char is not an instance of Integral. For example,
/* foo.h */
#ifndef FOO_H
#define FOO_H
char identichar(char c);
unsigned char identiuchar(unsigned char c);
signed char identischar(signed char c);
#endif/* foo.c */
#include "foo.h"
char identichar(char c) {
return c;
}
unsigned char identiuchar(unsigned char c) {
return c;
}
signed char identischar(signed char c) {
return c;
}-- Main.chs
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Foreign.C.String
#include "foo.h"
{#fun pure identichar as ^ { `Char' } -> `Char' #}
{#fun pure identiuchar as ^ { `Char' } -> `Char' #}
{#fun pure identischar as ^ { `Char' } -> `Char' #}
main :: IO ()
main = print $ map ($ 'A') [identichar, identiuchar, identischar]Preprocessing this with c2hs reveals this:
c2hs: Errors during expansion of binding hooks:
./Main.chs:9: (column 43) [ERROR] >>> Missing "out" marshaller!
There is no default marshaller for this combination of Haskell and C type:
Haskell type: Char
C type : CSChar
./Main.chs:8: (column 43) [ERROR] >>> Missing "out" marshaller!
There is no default marshaller for this combination of Haskell and C type:
Haskell type: Char
C type : CUChar
./Main.chs:7: (column 43) [ERROR] >>> Missing "out" marshaller!
There is no default marshaller for this combination of Haskell and C type:
Haskell type: Char
C type : CChar
So one must manually provide out marshallers:
import Foreign.C.String
import Foreign.C.Types
{#fun pure identichar as ^ { `Char' } -> `Char' castCCharToChar #}
{#fun pure identiuchar as ^ { `Char' } -> `Char' castCUCharToChar #}
{#fun pure identischar as ^ { `Char' } -> `Char' castCSCharToChar #}This, in turn, reveals the lack of in marshallers for Char:
c2hs: Errors during expansion of binding hooks:
./Main.chs:11: (column 31) [ERROR] >>> Missing "in" marshaller!
There is no default marshaller for this combination of Haskell and C type:
Haskell type: Char
C type : CSChar
./Main.chs:10: (column 31) [ERROR] >>> Missing "in" marshaller!
There is no default marshaller for this combination of Haskell and C type:
Haskell type: Char
C type : CUChar
./Main.chs:9: (column 31) [ERROR] >>> Missing "in" marshaller!
There is no default marshaller for this combination of Haskell and C type:
Haskell type: Char
C type : CChar
So the final workaround ends up being pretty verbose:
{#fun pure identichar as ^ { castCharToCChar `Char' } -> `Char' castCCharToChar #}
{#fun pure identiuchar as ^ { castCharToCUChar `Char' } -> `Char' castCUCharToChar #}
{#fun pure identischar as ^ { castCharToCSChar `Char' } -> `Char' castCSCharToChar #}Is it possible to have these marshallers be the defaults for Haskell's Char?