我正试图用Haskell代码编译一些 rust 迹代码.我用一个文件建立了一个测试系统,Fibonacci.hs带有一个函数,该函数在Haskell中计算斐波那契数,并通过Haskell的FFI将函数导出为fibonacci_hs(如下所示:https://github.com/nh2/haskell-from-python,尽管我将在底部复制和粘贴),在wrapper.c中定义了要导出的函数,用于初始化和退出Haskell的RTS.

代码如下所示:

{- Fibonacci.hs -}
{-# LANGUAGE ForeignFunctionInterface #-}

module Fibonacci 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

// wrapper.c

#include <stdlib.h>
#include "HsFFI.h"

void
example_init (void)
{
  hs_init (NULL, NULL);
}

void
example_exit (void)
{
  hs_exit ();
}

我通过以下方式编译这些文件:

ghc -c -dynamic -fPIC Fibonacci.hs

ghc -c -dynamic -fPIC wrapper.c

我通过以下方式将这些对象链接到一个共享/动态库(稍后将对此进行详细介绍):

ghc -o libfibonacci.so -shared -dynamic -fPIC Fibonacci.o wrapper.o -lHSrts

从链接的存储库中运行Python示例代码时,它在我的mac上运行良好,但我无法让它与Rust链接.

在Rust中,我的代码如下所示:

//main.rs
#[link(name = "fibonacci")]
extern {
    fn fibonacci_hs (n : i32); // c_int = i32
    fn fib_init (); // start hs rts
    fn fib_exit (); // kill hs rts
}

fn main () {
    unsafe {
        fib_init();
        for i in 0..100 {
            println!("{:?}th fibonacci : {:?}", i, fibonacci_hs(i));
        }
        fib_exit();
    }
}

我用rustc main.rs -L .编译(因为共享库文件是本地的).

在主程序库上编译时生成动态错误(然后在主程序库上生成ghc -o libfibonacci.so -shared -static haskell/Fibonacci.o haskell/wrapper.o -lHSrts个)在运行时:

dyld: Symbol not found: _ffi_call
  Referenced from: ./libfibonacci.so
  Expected in: flat namespace
 in ./libfibonacci.so
Trace/BPT trap: 5

提前谢谢你的帮助.

推荐答案

当你编译你的共享库时,看起来你也需要链接libffi:

ghc -o libfibonacci.dylib -shared -dynamic -fPIC \
  Fibonacci.hs wrapper.c -lHSrts -lffi

我通过进入我的GHC库目录(/usr/local/lib/ghc-7.10.1/rts)并搜索符号ffi_call得出了这个结论:

$ grep -lRa ffi_call .
./include/ffi.h
./rts/libHSrts-ghc7.10.1.dylib
...

然后,我用nm找到了确切的图书馆:

for i in *dylib; do
   if nm $i | grep -q 'T.*ffi_call'; then
       echo "== $i";
   fi;
done

然后我就可以用:

DYLD_LIBRARY_PATH='.' ./main

不幸的是,您的代码似乎不太正确,因为我只得到了一堆空元组.你忘了在函数上有一个返回类型,然后你遇到了一个问题,46次左右的斐波那契对于u32次太大了.

此外,您应该使用libc软件包中的类型,在这里使用u64可能是最安全的.

希望在其他地方安装相同的GHC.1模式.

Rust相关问答推荐

使用pyo3::Types::PyIterator的无限内存使用量

如何在Bevy/Rapier3D中获得碰撞机的计算质量?

新创建的变量的绑定生存期

为什么铁 rust S似乎有内在的易变性?

我是否可以在Ruust中修改 struct 实例上的字符串,以使其在修改后具有相同的字符串生存期?

从未排序的链表中删除重复项的铁 rust 代码在ELSE分支的低级上做了什么?

是否提供Bundle 在可执行文件中的warp中的静态文件?

使用启用优化的 alloc 会导致非法指令崩溃

从 rust 函数返回 &HashMap

Rust Axum 框架 - 解包安全吗?

为什么 Rust 字符串没有短字符串优化 (SSO)?

在Rust中实现Trie数据 struct 的更好方式

按下 Ctrl + C 时优雅地停止命令并退出进程

内部值发生变化时 Rc 的行为

为什么在 rust 中删除 vec 之前应该删除元素

如何在 Rust 中返回通用 struct

在 Traits 函数中设置生命周期的问题

如何用另一个变量向量置换 rust simd 向量?

HashMap entry() 方法使borrow 的时间比预期的长

Rust:为什么在 struct 中borrow 引用会borrow 整个 struct?