You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell FFI调用C函数时capi模式传递指针值不符合预期问题

Haskell调用C函数IupOpen出现指针类型不匹配警告问题

我尝试在Haskell侧调用如下声明的C函数:

int IupOpen(int *argc, char ***argv);

随后我编写了如下绑定代码:

foreign import capi "iup.h IupOpen"
    c_IupOpen :: Ptr CInt -> Ptr (Ptr CString) -> IO CInt
iupOpen :: Maybe [String]   -- ^ 程序命令行参数
        -> IO Int      -- ^ 初始化状态标志
iupOpen args = case args of
    Nothing -> fromIntegral <$> c_IupOpen nullPtr nullPtr
    Just argv -> alloca $ \argcPtr -> do
        poke argcPtr (fromIntegral . length $ argv)
        argvs <- mapM (`withCString` return) argv
        pCstr <- withArray argvs return
        argvPtr <- alloca $ \ppCstr -> poke ppCstr pCstr >> return ppCstr
        fromIntegral <$> c_IupOpen argcPtr argvPtr

编译后输出如下警告:

C:\...\AppData\Local\Temp\ghc6096_0\ghc_5.c: In function 'ghczuwrapperZC1ZChiupzm0zi1zi0zi0zm1ddNNYbMeka1JTSCkHxKK2ZCGraphicsziIUPziRawziIupZCIupOpen':
C:\...\AppData\Local\Temp\ghc6096_0\ghc_5.c:10:143: warning: passing argument 2 of 'IupOpen' from incompatible pointer type [-Wincompatible-pointer-types]
   10 | HsInt32 ghczuwrapperZC1ZChiupzm0zi1zi0zi0zm1ddNNYbMeka1JTSCkHxKK2ZCGraphicsziIUPziRawziIupZCIupOpen(void* a1, void*** a2) {return IupOpen(a1, a2);}    
      |                                                                                                                                               ^~       
      |                                                                                                                                               |        
      |                                                                                                                                               void *** 
In file included from C:\...\AppData\Local\Temp\ghc6096_0\ghc_5.c:7:
C:/.../hs/hs-iup/iup-3.30_Win64_mingw6_lib/include/iup.h:37:56: note: expected 'char ***' but argument is of type 'void ***'
   37 | IUP_API int       IupOpen          (int *argc, char ***argv);

但我传入的参数argvPtr确实是Ptr (Ptr CString)类型,我不理解为何会出现该警告,希望得到相关解答。

更新1

经过尝试我将capi替换为ccall后解决了问题,看起来capi生成的包装函数没有使用正确的类型签名。但我仍然不理解capi为何无法正常工作,这是GHC的bug还是我遗漏了什么配置?

更新2

我修改了代码避免了悬空指针问题,修改后代码如下:

foreign import capi "iup.h IupOpen"
    c_IupOpen :: Ptr CInt -> Ptr (Ptr CString) -> IO CInt
open :: Maybe [String]     -- ^ 程序命令行参数
     -> IO Int             -- ^ 初始化状态标志
open args = case args of
    Nothing -> fromIntegral <$> c_IupOpen nullPtr nullPtr
    Just argv -> alloca $ \ptrArgc -> do
        poke ptrArgc (fromIntegral . length $ argv)
        alloca $ \ptrCStr -> do
            cstrArr <- mapM newCString argv   -- 释放指针数组
            pokeArray ptrCStr cstrArr
            alloca $ \pptrCStr -> do
                poke pptrCStr ptrCStr
                flag <- c_IupOpen ptrArgc pptrCStr
                mapM_ free cstrArr
                return . fromIntegral $ flag

但除非使用ccall,否则指针类型仍然不匹配。

更新3

最终我查询到这是GHC的已知bug,对应issue #15531。


内容的提问来源于stack exchange,提问作者Z-Y.L

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 07:45:00