@KevinReid için, bunun c2hs ile nasıl yapılacağı ile ilgili bir örnek.
: dosyasında
charm.h
yılında enum
key
(Ben enum hiçbir fikrin var, bu yüzden sadece birkaç girilen değerleri)
typedef enum
{
PLAIN_KEY = 0,
SPECIAL_KEY = 1,
NO_KEY = 2
}
key;
key get_key();
Böyle c2hs en enum kanca kullanabilirsiniz Verilen
{#enum key as Key {underscoreToCase} deriving (Eq, Show)#}
Bir işleve bağlanmak için call
veya fun
'u kullanabilirsiniz. call
daha basittir, ancak herhangi bir marşlama yapmaz. İşte her ikisinin örnekleri. Ffi-sarılı get_key
bir CInt döndürecektir, bu nedenle ya elle (bir call
kullanıyorsa) marshaller (fun
kullanıyorsa) belirtmeniz gerekir. Burada kendi yazdım böylece c2hs enum marshallers içermez:
module Interface where -- file Interface.chs
{#enum key as Key {underscoreToCase} deriving (Eq, Show)#}
getKey = cIntToEnum `fmap` {#call get_key #}
{#fun get_key as getKey2 { } -> `Key' cIntToEnum #}
cIntToEnum :: Enum a => CInt -> a
cIntToEnum = toEnum . cIntConv
C2hs aşağıdaki (hafifçe temizlenir) bundan Haskell üretecektir:
data Key = PlainKey
| SpecialKey
| NoKey
deriving (Eq,Show)
instance Enum Key where
fromEnum PlainKey = 0
fromEnum SpecialKey = 1
fromEnum NoKey = 2
toEnum 0 = PlainKey
toEnum 1 = SpecialKey
toEnum 2 = NoKey
toEnum unmatched = error ("Key.toEnum: Cannot match " ++ show unmatched)
getKey = cIntToEnum `fmap` get_key
getKey2 :: IO (Key)
getKey2 =
getKey2'_ >>= \res ->
let {res' = cIntToEnum res} in
return (res')
cIntToEnum :: Enum a => CInt -> a
cIntToEnum = toEnum . cIntConv
foreign import ccall safe "foo.chs.h get_key"
get_key :: (IO CInt)
foreign import ccall safe "foo.chs.h get_key"
getKey2'_ :: (IO CInt)
hsc2hs bunun için bir makro var, ama mümkünse vanilya Haskell'i kullanmayı tercih ederim. – mcandre
Vanilla Haskell'de el yazmadan bunu yapamazsınız. hsc2hs ve c2hs'in her ikisi de enum kancalarına sahiptir ve bindings-dsl, CPP makrolarını kullanır. Bunlar sizin için Haskell türünü ve Enum örneğini otomatik olarak oluşturacaktır, ancak vanilya Haskell değildir. Tabii ki, ör. c2hs, önişlemciyi çalıştırın, sonra sadece sonuçtaki Haskell dosyasını gönderin, ancak bu genellikle hizalama ve ptr boyutları. –
Bunu yapmak için ağır araçlara gerek duymanızın sebebi, enum sabitlerinin C dilinde bir derleme zamanı yapısı olmasıdır - bunlar kütüphaneye bağlanma yoluyla alınabilen semboller değildir - böylece envanterin değerini bulmak C kaynak metnini analiz etmeyi gerektirir . –