到目前为止,我\xe2\x80\x99ve 还没有将 Haskell 库链接到 Rust 项目。我\xe2\x80\x99ve 有很多错误,最新的是recompile with -fPICfor ghc.
我\xe2\x80\x99已经设法获得动态链接\xe2\x80\x94的功能示例,但无法静态链接它。
\n现在附上我当前的设置:
\n构建.rs
\nfn main() {\n println!("cargo:rustc-link-search=native=deps");\n println!("cargo:rustc-link-lib=static=tesths");\n}\nRun Code Online (Sandbox Code Playgroud)\nsrc/main.rs
\nextern "C" {\n pub fn addTwo(x: i32) -> i32;\n pub fn init();\n pub fn fin();\n}\n\nfn main() {\n println!("Hello, world!");\n}\nRun Code Online (Sandbox Code Playgroud)\nsrc/haskell/Lib.hs
\nmodule Lib where\n\nimport Foreign.C.Types\n\naddTwo :: CInt -> CInt\naddTwo = (2 + )\n\nforeign export ccall addTwo :: CInt -> CInt\nRun Code Online (Sandbox Code Playgroud)\ncwrapper.c
\n#include <HsFFI.h>\n#ifdef __GLASGOW_HASKELL__\n#include "Lib_stub.h"\n#endif\n#include <stdio.h>\n\nvoid init(void) {\n static char *argv[] = {"libhs.so", 0}, **argv_ = argv;\n static int argc = 1;\n\n hs_init(&argc, &argv_);\n}\n\nvoid fin(void) { hs_exit(); }\nRun Code Online (Sandbox Code Playgroud)\n我用 编译#4 ghc -c -static -lHSrts -lffi cwrapper.c,得到cwrapper.o. 同样,我ghc -c -static -fPIC -lffi Lib.hs也使用 #3 进行编译并获取目标代码。
完成后,我将继续将这两个文件存档ar rcs libtesths.a Lib.o cwrapper.o。
在cargo build:
note: /usr/bin/ld: deps/libtesths.a(Lib.o):(.text+0x29): undefined reference to `newCAF\'\n /usr/bin/ld: deps/libtesths.a(Lib.o):(.text+0x39): undefined reference to `stg_bh_upd_frame_info\'\n /usr/bin/ld: deps/libtesths.a(Lib.o):(.text+0x48): undefined reference to `base_ForeignziCziTypes_zdfNumCInt_closure\'\n /usr/bin/ld: deps/libtesths.a(Lib.o):(.text+0x4f): undefined reference to `stg_ap_p_info\'\n\xe2\x80\xa6\nRun Code Online (Sandbox Code Playgroud)\n我\xe2\x80\x99 有一种预感,libHSrts 不是\xe2\x80\x99t 由于某种原因被静态链接。
\n我遵循 Shepmaster\xe2\x80\x99s 的建议并成功制作了一个工作示例。但我\xe2\x80\x99m 现在与我的 Rust 执行程序链接时遇到问题。
\n我使用 stack 和ghc-options: -staticlib -stubdir .来c-sources: cwrapper.c构建。当我尝试使用以下命令构建 Rust 项目时cargo rustc \xe2\x80\x94 -C relocation-model=static:
/usr/bin/ld: deps/liba.a(Type.o): in function `integerzmwiredzmin_GHCziIntegerziType_zdwplusBigNatWord_info\'\n(.text.integerzmwiredzmin_GHCziIntegerziType_zdwplusBigNatWord_info+0x128): undefined reference to `__gmpn_add_1\'\n/usr/bin/ld: deps/liba.a(Type.o): in function\n`integerzmwiredzmin_GHCziIntegerziType_zdwminusBigNatWord_info\'\n(.text.integerzmwiredzmin_GHCziIntegerziType_zdwminusBigNatWord_info+0xdf): undefined reference to `__gmpn_sub_1\'\n/usr/bin/ld: deps/liba.a(Type.o): in function `integerzmwiredzmin_GHCziIntegerziType_complementInteger_info\'\n(.text.integerzmwiredzmin_GHCziIntegerziType_complementInteger_info+0x138): undefined reference to `__gmpn_sub_1\'\n/usr/bin/ld: deps/liba.a(Type.o): in function `integerzmwiredzmin_GHCziIntegerziType_zdwtimesBigNatWord_info\'\n(.text.integerzmwiredzmin_GHCziIntegerziType_zdwtimesBigNatWord_info+0x158): undefined reference to `__gmpn_mul_1\'\nRun Code Online (Sandbox Code Playgroud)\n还提到了一个wrappers.o. 任何帮助表示赞赏。
我也gmp通过设置build.rs链接解决了问题。libgmp不过,我现在有一个不同的问题。
\nnote: /usr/bin/ld: deps/libhssource.a(Lib.o): in function `testFFI\':\n (.text+0x88fd): multiple definition of `testFFI\'; deps/libhssource.a(Lib.o):(.text+0x1b66): first defined here\n /usr/bin/ld: deps/libhssource.a(cwrapper.o): in function `init\':\n cwrapper.c:(.text+0x0): multiple definition of `init\'; deps/libhssource.a(cwrapper.o):cwrapper.c:(.text+0x0): first defined here\n /usr/bin/ld: deps/libhssource.a(cwrapper.o): in function `fin\':\n cwrapper.c:(.text+0x20): multiple definition of `fin\'; deps/libhssource.a(cwrapper.o):cwrapper.c:(.text+0x1a): first defined here\n collect2: error: ld returned 1 exit status\nRun Code Online (Sandbox Code Playgroud)\n这是完成此任务的最终构建命令:
\ncargo rustc -- -C relocation-model=static -Clink-arg=-Wl,--allow-multiple-definition\nRun Code Online (Sandbox Code Playgroud)\n使用RUSTFLAGS将导致构建崩溃,因为它使用静态重定位模型构建所有依赖项,这在我的情况下无法为 crate \xe2\x80\x94 工作 \xe2\x80\x99 rustversion。它会报告recompile with -fPIC错误。
我立即编译了 Haskell 库和 C shim,并传递了-staticlib标志:
ghc -c -staticlib Lib.hs cwrapper.c -o libtesths.a
Run Code Online (Sandbox Code Playgroud)
然后我调用这些函数:
extern "C" {
pub fn addTwo(x: i32) -> i32;
pub fn init();
pub fn fin();
}
fn main() {
unsafe {
init();
println!("{}", addTwo(40));
fin();
}
}
Run Code Online (Sandbox Code Playgroud)
% cargo run -q
42
Run Code Online (Sandbox Code Playgroud)
这对我在使用 GHC 8.10.7 的 Apple Silicon 处理器上的 macOS 12.0.1 上有效。
如果您使用的是 x86_64 Linux,则可能需要添加RUSTFLAGS='-C relocation-model=static'.