inline-c:“`Type` 不能在外部调用中编组”

inline-c : "`Type` cannot be marshalled in a foreign call"

设置

C 枚举类型由 c2hs 呈现为 Haskell,并带有 Storable 正确编译的实例 (TypesC2Hs.chs)。我将此不合格导入到我为 inline-c 上下文 (Internal.hs) 分配的模块中。 c2hs 生成的 .hs 模块和 Internal.hs 都由 InlineC.hs 导入,另一个 inline-c 模块包含包装 C 调用的准引号。

TypesC2Hs.hs ------------- 
    |                    |
    V                    V
Internal.hs -------> InlineC.hs

问题

InlineC.hs 抱怨无法编组此类型:"Unacceptable argument type in foreign declaration: ‘DMBoundaryType’ cannot be marshalled in a foreign call When checking declaration:"

这是怎么回事?这是 inline-c 第一次给我这种错误类型。

我应该注意到不需要直接取消引用的其他类型,例如newtype DM = DM (Ptr DM) deriving Storable,使用上述方法效果很好。

提前致谢


TypesC2Hs.chs

{# enum DMBoundaryType as DMBoundaryType {underscoreToCase} deriving (Eq, Show) #}

instance Storable DMBoundaryType where
  sizeOf _ = {# sizeof DMBoundaryType #}
  alignment _ = {# alignof DMBoundaryType #}
  peek = peek
  poke = poke

Internal.hs

{-# LANGUAGE QuasiQuotes, TemplateHaskell ,GeneralizedNewtypeDeriving, StandaloneDeriving ,DeriveDataTypeable, DataKinds, OverloadedStrings #-}

module Internal where

import TypesC2Hs

import qualified Language.C.Inline         as C
import qualified Language.C.Types          as CT
import           Language.C.Inline.Context

import qualified Language.Haskell.TH       as TH

import           Data.Monoid               ((<>), mempty)
import qualified Data.Map                  as Map


ctx :: Context
ctx = baseCtx <> funCtx <> vecCtx <> bsCtx <> pctx where
  pctx = mempty {ctxTypesTable = typesTable}


typesTable :: Map.Map CT.TypeSpecifier TH.TypeQ  
typesTable = Map.fromList
              [ (CT.TypeName "DMBoundaryType", [t| DMBoundaryType |])  ]

InlineC.hs

dmdaCreate1d0' cc bx m dof s =
   withPtr ( \ dm -> [C.exp|int{DMDACreate1d($(int c),
                                              $(DMBoundaryType bx),
                                              $(PetscInt m),
                                              $(PetscInt dof),
                                              $(PetscInt s),
                                              NULL,
                                              $(DM* dm))}|]  )
  where c = unComm cc

C enum 不是 marshallable foreign type, that is what compiler tries to tell you. To work around it, pass it as a CInt using fromEnum (looks like c2hs now supports it via hooks,但我没试过。)