我熟悉從這里定義的 C 呼叫 Haskell 函式的方法:
https://wiki.haskell.org/Calling_Haskell_from_C
但是,我想做的不是創建一個可執行檔案,而是創建一個.o稍后將與其他檔案鏈接的.o檔案。我的場景是這樣的:
安全.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Safe where
import Foreign.C.Types
fibonacci :: Int -> Int
fibonacci n = fibs !! n
where fibs = 0 : 1 : zipWith ( ) fibs (tail fibs)
fibonacci_hs :: CInt -> CInt
fibonacci_hs = fromIntegral . fibonacci . fromIntegral
foreign export ccall fibonacci_hs :: CInt -> CInt
但是C檔案不同,沒有main函式
測驗.c
#include <HsFFI.h>
#ifdef __GLASGOW_HASKELL__
#include "Safe_stub.h"
#endif
int foo()
{
int i;
// some dummy values for argc and argv
hs_init(&argc, &argv);
i = fibonacci_hs(42);
hs_exit();
return i;
}
現在要將它們鏈接到一個 .o 檔案中,我嘗試了這樣的操作:
ghc -fPIE -c -O Safe.hs
發出Safe_stub.h,Safe.o和Safe.hi檔案。
接下來,我將test.c檔案編譯成目標檔案
ghc --make -fPIE -no-hs-main -optc-O -c test.c -o test.o
給我我正在尋找的test.o目標檔案。
現在,我嘗試鏈接生成的兩個目標檔案并使用 ghc 的聯結器(內部使用 gcc):
ghc -no-hs-main -optc-nostartfiles -optc-static-pie test.o Safe.o -o result.o
這是我得到的
/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crt1.o:function _start: error: undefined reference to 'main'
collect2: error: ld returned 1 exit status
`x86_64-linux-gnu-gcc' failed in phase `Linker'. (Exit code: 1)
因此,目標檔案似乎在某個地方參考了main. 是傳遞一些標志的問題嗎?或者我做錯了什么?提前致謝!
編輯
有人建議使用 plainld -r鏈接目標檔案。這種方法的問題在于,如果ld使用 vanilla,它不會在 Haskell 運行時中鏈接,以使目標檔案實際有用并且可以被另一個 C 程式作為庫呼叫。
如果我的帖子不清楚,我想創建一個 .o 檔案,它可以用作呼叫 Haskell 代碼的 C 庫。
uj5u.com熱心網友回復:
通常,聯結器用于將多個目標檔案組合成一個可執行檔案,它自然必須有一個main作為其入口點。顯然,可以將多個目標檔案組合成一個目標檔案,使用ld -r. GHC 是否有這樣的行為標志?也許吧,但我無法立即找到它。
但是如果你只是打算使用 GHC 來呼叫聯結器,為什么不自己呼叫聯結器呢?
ld -r test.o Safe.o -o result.o
uj5u.com熱心網友回復:
經過大量使用各種標志后,這是我對問題的解決方案
ghc -c -O Safe.hs
ghc -c -no-hs-main -optc-O test.c
我不知道--make國旗添加了什么。現在想象一下,您從上面分發Safe.o和test.o生產。使用實際上具有main如下方法的 C 函式編譯它:
測驗foo.c
extern int foo();
int main(){
int k = foo();
return k;
}
你會這樣做:
ghc -no-hs-main testfoo.c test.o Safe.o
生成的可執行檔案當然會鏈接 Haskell 運行時。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/528525.html
標籤:C哈斯克尔链接器ghc菲
