Đối với @KevinReid, đây là ví dụ về cách thực hiện việc này với c2hs.
Với enum key
trong file charm.h
(Tôi không có ý tưởng những gì trong enum, vì vậy tôi chỉ điền vào một vài giá trị)
typedef enum
{
PLAIN_KEY = 0,
SPECIAL_KEY = 1,
NO_KEY = 2
}
key;
key get_key();
Bạn có thể sử dụng móc enum c2hs của như thế này:
{#enum key as Key {underscoreToCase} deriving (Eq, Show)#}
Để liên kết với một hàm, bạn có thể sử dụng call
hoặc fun
. call
là đơn giản hơn, nhưng không làm bất kỳ marshaling. Dưới đây là ví dụ về cả hai. Các f2i bọc get_key
sẽ trả về một CInt, vì vậy bạn cần phải tự sắp xếp nó (nếu sử dụng call
) hoặc chỉ định trình soạn thảo (nếu sử dụng fun
). c2hs không bao gồm marshallers enum vì vậy tôi đã viết riêng của tôi ở đây:
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 sẽ tạo ra Haskell sau từ này (hơi dọn dẹp):
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)
Nguồn
2011-10-10 18:01:42
hsc2hs có một macro cho điều này, nhưng tôi chỉ muốn sử dụng vanilla Haskell nếu có thể. – mcandre
Bạn không thể làm điều đó trong vanilla Haskell mà không cần viết tất cả bằng tay. hsc2hs và c2hs đều có móc enum, và bindings-dsl sử dụng các macro CPP. Chúng sẽ tự động tạo kiểu Haskell và cá thể Enum cho bạn, nhưng nó không phải là vanilla Haskell. Tất nhiên bạn có thể viết nó với ví dụ c2hs, chạy bộ tiền xử lý, sau đó chỉ gửi tệp Haskell kết quả, nhưng điều đó thường gây ra sự cố với ví dụ: kích thước liên kết và ptr. –
Lý do bạn cần các công cụ hạng nặng để thực hiện điều này là các hằng số enum là một cấu trúc biên dịch trong C - chúng không được xuất ra bằng cách liên kết tới thư viện - do đó khám phá giá trị của enums yêu cầu phân tích văn bản nguồn C . –