从Rust中调用动态链接的Haskell代码 [英] Calling dynamically linked Haskell code from Rust

查看:143
本文介绍了从Rust中调用动态链接的Haskell代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



代码如下所示:

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

模块斐波纳契其中

导入Foreign.C.Types

fibonacci :: Int - > Int
fibonacci n = fibs !! n
其中fibs = 0:1:zipWith(+)fibs(尾纤)

fibonacci_hs :: CInt - > CInt
fibonacci_hs = fromIntegral。斐波纳契。 fromIntegral

国外出口ccall fibonacci_hs :: CInt - > CI






  // wrapper.c 

#include< stdlib.h>
#includeHsFFI.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(); //开始hs rts
fn fib_exit(); //杀死hs rts
}

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


$ / code>

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



在Mac上生成的错误( ghc -o libfibonacci.so -shared -static haskell / Fibonacci.o haskell / wrapper.o -lHSrts then'rustc main.rs -L。)在运行时:

  dyld:找不到符号:_ffi_call 
引用自./libfibonacci.so
预计于: flat命名空间
in ./libfibonacci.so
Trace / BPT trap:5

感谢您提前提供任何帮助。当您编译共享库时,它看起来像需要链接到<$

c $ c> 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 来找到确切的库:

 用于i in * dylib;如果nm $ i |则执行
grep -q'T. * ffi_call';那么
会回显== $ i;
fi;
完成

然后我可以运行:

  DYLD_LIBRARY_PATH ='。'./main 



不幸的是,看起来你的代码并不完全正确,因为我刚刚得到一堆空元组。你忘了在函数中有一个返回类型,然后你遇到了一个问题,即第46个左右的Fibbonacci对于 u32 来说太大了。



此外,您应该使用 libc 包中的类型,并且使用 u64可能最安全



我已经使用Homebrew安装了GHC 7.10.1,但希望相同的模式可以在其他地方使用。


I'm trying to compile some Rust code with some Haskell code. I have a test system set up with a file, Fibonacci.hs with a function which computes fibonacci numbers in Haskell and exports the function as fibonacci_hs via Haskell's FFI (as here: https://github.com/nh2/haskell-from-python, though I'll copy and paste at the bottom), and in wrapper.c have defined the functions to export to be called for initializing and exiting Haskell's RTS.

The code looks like this:

{- 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 ();
}

I compile these via:

ghc -c -dynamic -fPIC Fibonacci.hs

ghc -c -dynamic -fPIC wrapper.c

and I link the objects into a shared/dynamic library (more on this in a second) via:

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

On running the Python example code from the linked repository, it runs just fine on my mac, but I can't get it to link with Rust.

In Rust my code looks something like this:

//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();
    }
}

And I compile with rustc main.rs -L . (since shared library file is local).

The error I generate on Mac, when compiled with a dynamic library (ghc -o libfibonacci.so -shared -static haskell/Fibonacci.o haskell/wrapper.o -lHSrts then 'rustc main.rs -L . ) is at runtime:

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

Thanks for any help in advance.

解决方案

When you compile your shared library, it looks like you need to link against libffi as well:

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

I deduced this by going into my GHC library directory (/usr/local/lib/ghc-7.10.1/rts) and then grepping for the symbol ffi_call:

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

I then used nm to find which exact library had it:

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

I was then able to run with:

DYLD_LIBRARY_PATH='.' ./main

Unfortunately, it appears your code isn't quite right, as I just get a bunch of empty tuples. You forgot to have a return type on the function, and then you run into a problem that the 46th or so Fibbonacci is too big for a u32.

Additionally, you should be using the types from the libc package, and it may be safest to use a u64 here.

I have installed GHC 7.10.1 using Homebrew, but hopefully the same pattern would work elsewhere.

这篇关于从Rust中调用动态链接的Haskell代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆