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

使用GHC构建Haskell+C共享库链接报未定义引用错误如何解决?

错误原因

你遇到的未定义引用错误根源是:stg_writeTVarzh这类符号都属于GHC的核心运行时库(RTS)。你直接用GHC链接目标文件时,GHC会自动加入所有Haskell运行时、基础库的链接参数,因此可以正常编译。但你用gcc直接链接共享库时,gcc不会自动查找并链接GHC相关的依赖库,因此报错。

首先修正你代码里的笔误:你lib.c中引入的Foo_stub.h是错误的,你的Haskell模块名为Add,GHC生成的stub头文件名为Add_stub.h,需要先把这行修改为#include "Add_stub.h"。


正确构建步骤

步骤1:编译Haskell模块

ghc -c Add.hs -dynamic -fPIC -odir ./obj -stubdir ./include

参数说明:

  • -fPIC生成位置无关代码,符合共享库要求
  • -stubdir ./include将生成的FFI头文件输出到include目录

步骤2:编译C封装代码

gcc -c lib.c -o ./obj/lib.o -I ./include -I $(ghc --print-libdir)/include -fPIC

这里用ghc --print-libdir自动获取GHC安装路径,避免写死路径的兼容性问题。

步骤3:链接生成共享库

ghc -dynamic -shared -fPIC ./obj/lib.o ./obj/Add.o -o libadd.so

用GHC执行链接操作,会自动处理Haskell相关的依赖关联,不需要手动加库参数。

步骤4:链接主程序(两种方式二选一)

方式1:用GHC链接(推荐,不易出错)

GHC会自动加入所有运行时依赖的链接参数:

ghc test.c -o test-exe -no-hs-main -L. -ladd -Wl,-rpath=.

参数说明:

  • -no-hs-main告诉GHC程序入口是C的main函数,不是Haskell的main
  • -Wl,-rpath=.指定运行时优先从当前目录查找libadd.so,避免运行时找不到库的问题

方式2:用gcc链接

需要手动指定GHC运行时库的路径和依赖:

gcc test.c -o test-exe -L. -ladd -L$(ghc --print-libdir)/rts -lHSrts-ghc8.6.5 -Wl,-rpath=$(ghc --print-libdir)/rts -Wl,-rpath=.

两种方式生成的test-exe都可以正常运行。


内容的提问来源于stack exchange,提问作者varajala

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 20:48:01