【发布时间】:2010-12-11 20:54:16
【问题描述】:
我一直认为用 haskell 创建 midori 插件会很好,但这似乎几乎是不可能的。问题在于通过 ffi 导出 haskell 函数,因为 ghc 编译器使用了大量的 -u 开关。
有没有人看到在类似的情况下使用了haskell,而不必将gcc替换为ghc?如果是这样,它是如何解决的?他们经历了哪些圈套?
编辑:要求提供一些示例,所以在这里:
export.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Export where
import Foreign.C
import Foreign.C.Types
foo :: IO Int
foo = return 2
foreign export ccall foo :: IO Int
test.c(ifdefs 被剪断)
#include <stdio.h>
#include "HsFFI.h"
#include "export_stub.h"
extern void __stginit_Export(void);
int main(int argc, char **argv)
{
int i;
hs_init(&argc, &argv);
hs_add_root(__stginit_Export);
i = foo();
printf("%d\n", i);
hs_exit();
return 0;
}
用ghc --make -no-hs-main export.hs test.c 编译会创建一个a.out
可执行的工作。 ghc 使用以下命令进行链接:
collect2 --build-id --eh-frame-hdr -m elf_i386 --hash-style=both -dynamic-linker /lib/ld-linux.so.2 -o a.out -z relro -u ghczmprim_GHCziTypes_Izh_static_info -u ghczmprim_GHCziTypes_Czh_static_info -u ghczmprim_GHCziTypes_Fzh_static_info -u ghczmprim_GHCziTypes_Dzh_static_info -u base_GHCziPtr_Ptr_static_info -u base_GHCziWord_Wzh_static_info -u base_GHCziInt_I8zh_static_info -u base_GHCziInt_I16zh_static_info -u base_GHCziInt_I32zh_static_info -u base_GHCziInt_I64zh_static_info -u base_GHCziWord_W8zh_static_info -u base_GHCziWord_W16zh_static_info -u base_GHCziWord_W32zh_static_info -u base_GHCziWord_W64zh_static_info -u base_GHCziStable_StablePtr_static_info -u ghczmprim_GHCziTypes_Izh_con_info -u ghczmprim_GHCziTypes_Czh_con_info -u ghczmprim_GHCziTypes_Fzh_con_info -u ghczmprim_GHCziTypes_Dzh_con_info -u base_GHCziPtr_Ptr_con_info -u base_GHCziPtr_FunPtr_con_info -u base_GHCziStable_StablePtr_con_info -u ghczmprim_GHCziBool_False_closure -u ghczmprim_GHCziBool_True_closure -u base_GHCziPack_unpackCString_closure -u base_GHCziIOziException_stackOverflow_closure -u base_GHCziIOziException_heapOverflow_closure -u base_ControlziExceptionziBase_nonTermination_closure -u base_GHCziIOziException_blockedIndefinitelyOnMVar_closure -u base_GHCziIOziException_blockedIndefinitelyOnSTM_closure -u base_ControlziExceptionziBase_nestedAtomically_closure -u base_GHCziWeak_runFinalizzerBatch_closure -u base_GHCziTopHandler_runIO_closure -u base_GHCziTopHandler_runNonIO_closure -u base_GHCziConc_ensureIOManagerIsRunning_closure -u base_GHCziConc_runSparks_closure -u base_GHCziConc_runHandlers_closure /usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/crt1.o /usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/crti.o /usr/lib/gcc/i486-linux-gnu/4.4.3/crtbegin.o -L/usr/lib/ghc-6.12.1/base-4.2.0.0 -L/usr/lib/ghc-6.12.1/integer-gmp-0.2.0.0 -L/usr/lib/ghc-6.12.1/ghc-prim-0.2.0.0 -L/usr/lib/ghc-6.12.1 -L/usr/lib/gcc/i486-linux-gnu/4.4.3 -L/usr/lib/gcc/i486-linux-gnu/4.4.3 -L/usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/i486-linux-gnu/4.4.3/../../.. -L/usr/lib/i486-linux-gnu export.o export_stub.o test.o -lHSbase-4.2.0.0 -lHSinteger-gmp-0.2.0.0 -lgmp -lHSghc-prim-0.2.0.0 -lHSrts -lm -lffi -lrt -ldl -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i486-linux-gnu/4.4.3/crtend.o /usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/crtn.o
从 上一个命令没有编译并返回(大约 50 个或更多 行)
/usr/lib/ghc-6.12.1/libHSrts.a(RtsAPI.o): In function `rts_mkFunPtr':
(.text+0x5a9): undefined reference to `base_GHCziPtr_FunPtr_con_info'
/usr/lib/ghc-6.12.1/libHSrts.a(RtsAPI.o): In function `rts_mkString':
(.text+0x60f): undefined reference to `base_GHCziPack_unpackCString_closure'
【问题讨论】:
-
这可能是手册的相关部分:haskell.org/ghc/docs/latest/html/users_guide/ffi-ghc.html 具体参见 8.2.1.2。您可以制作一个用 Haskell 编写的库,并且可以从 C 代码中调用。然后你只需要在 C 中编写一些胶水代码就可以变成插件或其他任何东西。不过不是我自己做的,请等待更多有经验的“外贸出口”用户解答。
-
@Jetxee,您是否知道将答案写为评论会禁止 OP 接受它? :)
-
是的,你是对的,但是当试图链接这些对象时,会导致未定义的错误,可以使用 -u 开关修复,但它们有很多,我 认为 他们可能会因程序而异
-
@Kos 好的,我将其发布为答案 :) @Masse 您能否发布一个最小的编译示例,您尝试构建它的具体方式以及错误是什么。然后有人可能会尝试解决您的特定问题。