11

printfHaskellのForeign Function Interfaceで可変引数(例:)を持つC関数を使用する例を誰かに教えてもらえますか?HaskellWiki を検索してみましたが、そのような例は見つかりませんでした。

ありがとう!

4

4 に答える 4

7

それは不可能だと思います。ただし、同じ C 関数の複数の外部インポートを作成して、それに異なる Haskell 名と Haskell タイプを与えることはできます。ただし、100% 移植可能かどうかはわかりません。

于 2011-05-13T09:08:17.410 に答える
5

Haskell インターフェイスを libffi (http://hackage.haskell.org/package/libffi) に使用できます。このコードは、私が取り組んでいるプロジェクトからそのままコピーしたものです ( https:/でコンテキストで確認できます)。 /github.com/mokus0/bindings-hdf5/blob/master/src/Bindings/HDF5/Raw/H5E.hsc )。この特定の関数は、引数がない場合もチェックし、可能な場合は C 関数を直接呼び出して、libffi に関連する小さなオーバーヘッドを回避します。

-- libffi to the rescue!  I have no idea how I'd wrap this without it, and there
-- doesn't appear to be a non-deprecated non-private non-varargs equivalent.
-- 
-- |Pushes a new error record onto error stack for the current
-- thread.  The error has major and minor IDs 'maj_id' and
-- 'min_id', the name of a function where the error was detected,
-- the name of the file where the error was detected, the
-- line within that file, and an error description string.  The
-- function name, file name, and error description strings must
-- be statically allocated.
-- 
-- Returns non-negative on success/Negative on failure.
-- 
-- > herr_t H5Epush2(hid_t err_stack, const char *file, const char *func, unsigned line,
-- >     hid_t cls_id, hid_t maj_id, hid_t min_id, const char *msg, ...);
--
-- (msg is a printf format string, the varargs are the format parameters)
h5e_push2 :: HId_t -> CString -> CString -> CUInt -> HId_t -> HId_t -> HId_t -> CString -> [Arg] -> IO HErr_t
h5e_push2 err_stack file func line cls_id maj_id min_id fmt [] =
    h5e_push2_no_varargs err_stack file func line cls_id maj_id min_id fmt
h5e_push2 (HId_t err_stack) file func line (HId_t cls_id) (HId_t maj_id) (HId_t min_id) fmt varargs =
    callFFI p_H5Epush2 retHErr_t args
    where 
        argHId_t = arg#type hid_t
        retHErr_t = fmap HErr_t (ret#type herr_t)

        args = argHId_t err_stack : argPtr file : argPtr func : argCUInt line
             : argHId_t cls_id : argHId_t maj_id : argHId_t min_id : argPtr fmt
             : varargs

foreign import ccall "H5Epush2"
    h5e_push2_no_varargs :: HId_t -> CString -> CString -> CUInt -> HId_t -> HId_t -> HId_t -> CString -> IO HErr_t
foreign import ccall "&H5Epush2"
    p_H5Epush2 :: FunPtr (HId_t -> CString -> CString -> CUInt -> HId_t -> HId_t -> HId_t -> CString -> IO HErr_t)
于 2011-05-13T14:23:45.520 に答える
1

最近のバージョンの GHC では、このCApiFFI拡張機能を使用して、可変引数の C 関数をインポートできます。

GHC ユーザーズ ガイド - CAPI 呼び出し規約

于 2016-09-09T17:56:29.253 に答える