1

FFIをpdflibに書き込んでいます。Pdflib C APIには、さまざまなハンドル(ドキュメント、ページ、画像、フォント)をプレーンな整数(ポインターではない)として返す、または受け取る関数がたくさんあります。

誤って間違ったパラメーターを関数に渡さないようにするために、次の形式で一連のニュータイプを作成します。

newtype PdiDoc = PdiDoc Int
newtype PdiPage = PdiPage Int
newtype PdfImage = PdfImage Int
newtype PdfFont = PdfFont Int

今、私はそれらのタイプのマーシャラーを提供する必要があります。

image2c (PdfImage i) = fromIntegral i
font2c (PdfFont f) = fromIntegral f
pdipage2c (PdiPage i) = fromIntegral i

ご覧のとおり、マーシャラーはまったく同じですが、タイプが異なります。

だから私の質問は、ある種のタイプマジック、SYB vodooトリックがあり、それらすべてのタイプをマーシャリングするために1つの関数だけを持つことができますか、それとも異なるニュータイプに対して同じ関数を何度も作成する必要がありますか?

編集:それが私の問題を解決したので、私はドンの答えを受け入れました。

スイッチを入れました

GeneralizedNewtypeDeriving 

追加した

deriving (Eq, Ord, Num, Enum, Real, Integral)

私のニュータイプのそれぞれに、そして今、私はそれらすべてをマーシャルするために標準のfromIntegralを使うことができます。

ネイサンハウエルの答えも正しいものです、私はそれを賛成しました。しかし残念ながら、彼の解決策は、私が使用しているc2hsのようなFFIプリプロセッサをあきらめることを意味します。

4

2 に答える 2

7

GHCのFFI拡張機能では、FFIプリミティブをラップするニュータイプを使用できます。インポートされた関数のシグネチャを変更して、newtypesを使用し、(うまくいけば)手動でラップを解除する必要をなくすことができます。

{-# LANGUAGE ForeignFunctionInterface #-}

module Main where

newtype Foo = Foo Int

foreign import ccall someCall :: Foo -> IO Foo

main :: IO ()
main = do
  Foo x <- someCall (Foo 1)
  print x

または、新しいGHC Generics機能(7.2.1以降で使用可能)を使用すると、新しいタイプのジェネリックアンパックと再パックが可能になります。

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE TypeFamilies #-}

module Main where

import GHC.Generics

-- use a regular newtype
newtype Foo1 = Foo1 Int deriving (Generic, Show)

-- or with record syntax
newtype Foo2 = Foo2{foo2 :: Int} deriving (Generic, Show)

unpack :: (Generic a, Rep a ~ D1 dc (C1 cc (S1 sc (K1 R kc)))) => a -> kc
unpack = unK1 . unM1 . unM1 . unM1 . from

pack :: (Generic a, Rep a ~ D1 dc (C1 cc (S1 sc (K1 R kc)))) => kc -> a
pack = to . M1 . M1 . M1 . K1

-- the C import uses Ints
foreign import ccall "someCall" c'someCall :: Int -> IO Int

-- and the typed wrapper packs/unpacks to FFI primitives
someCall :: Foo1 -> IO Foo2
someCall = fmap pack . c'someCall . unpack

main :: IO ()
main = do
  Foo2 x <- someCall (Foo1 1)
  print x
于 2012-05-08T18:15:39.537 に答える
3

を使用して、型の「Num」を導出できますGeneralizedNewtypeDeriving。これは、リテラルと演算子を少し使用するのに役立ちます。

マーシャリングには、hsc2hsなどのFFI前処理を使用します。これにより、ニュータイプのラッピングとアンラッピングを自動化できます。

RWHの例:

ここに画像の説明を入力してください

于 2012-05-08T18:15:10.853 に答える