通过 FFI 在 Haskell 和 Ruby 之间进行绑定?

7

由于Ruby和Haskell都支持FFI,

  • 是否有可能通过FFI从Ruby调用Haskell代码?
  • 在Ruby中是否有任何Haskell绑定?
6个回答

11

我有点晚来参加这个讨论,但目前我正在编写一个Ruby和Haskell之间的桥接器。它在http://github.com/mwotton/Hubris上 - 这是一个在C层面工作的绑定。虽然还处于早期开发阶段。


8

GHC 6.12.1支持在Linux上构建动态库。尝试类似以下命令:

Example.hs

{-# LANGUAGE ForeignFunctionInterface #-}

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

script.rb

require 'dl'
require 'dl/import'

module Example
    extend DL::Importable
    dlload "./libffi-example.so"
    extern "void example_init()"
    extern "void example_exit()"
    extern "int fibonacci_hs(int)"
end

Example.example_init

1.upto( 40 ) do | x |
    puts "#{ x } -> #{ Example.fibonacci_hs x }\n"
end

Example.example_exit

Makefile

GHC=ghc-6.12.1

libffi-example.so: Example.o wrapper.o Example_stub.o
    $(GHC) -o $@ -shared -dynamic -fPIC $^ -lHSrts-ghc6.12.1

Example_stub.c Example_stub.h Example.o: Example.hs
    $(GHC) -c -dynamic -fPIC Example.hs

Example_stub.o: Example_stub.c
    $(GHC) -c -dynamic -fPIC Example_stub.c

wrapper.o: wrapper.c Example_stub.h
    $(GHC) -c -dynamic -fPIC wrapper.c

clean:
    rm -f *.hi *.o *_stub.[ch] *.so

运行命令

make
ruby script.rb

6

我之前没有见过这样的做法,但是这是可能的。

  • 使用 Haskell 的 FFI 来包装 libruby。您的主要可执行文件将由 Haskell 编写,它将调用 ruby_init() 和相关函数以在进程内运行 Ruby 解释器。这确实允许您运行任意的 Ruby 代码。
  • 使用 Ruby 的 FFI 将 GHC 模块 作为库 包装起来。您的 Ruby 脚本必须调用 hs_init(),并且只能访问 foreign export 函数。

您需要编写一些粘合代码,其中一些是 C 语言,以使这两个选项中的任何一个都能正常工作。

  • 使用某些IPC在不同的进程中运行Ruby和Haskell,并在它们之间进行通信。也许可以使用XML-RPC(Haskell/Ruby)或JSON(Haskell/Ruby),或者甚至只是使用自己的自定义协议进行管道通信。

我不知道您的要求是什么,但这是我会选择的方式——它要容易得多。


1

0

@ephemient,我正在寻找一些使用Ruby(高级+动态)作为主控制逻辑并调用Haskell进行大量数据处理(功能+速度)的方法。

我认为本地绑定接近不存在,除了这条推文http://twitter.com/BlurredWeasel/status/1321484127

使用JSON RPC可能是实现最简单的方法,在Ruby中有一个薄包装器(method_missing),可以通过JSON / Socket调用Haskell。

JSON具有将基元轻松映射到各种语言之间的本机类型的优点。

class SciHs
  def method_missing(method, *args) 
     // json encode
     // request Haskell over tcp socket or unix pipes
     // json decode
  end
end 

在 Ruby 中进行快速数字计算的其他替代方案(+ 函数式风格)

  • NArray 或其他科学库
  • GNU Scientific Library 的 Ruby 绑定
  • 或者升级到 Ruby 1.9 并使用 YARV2LLVM 将计算逻辑 JIT 到 LLVM 中以实现更快的执行。

有什么想法吗?


JSON在Haskell中很容易处理;我在这里有一个基于JSON的线协议实现:http://github.com/jrockway/app-persistent/blob/905f90b16a536baa09082b9083185f16323c51b5/client/App/Persistent/Client/Message.hs - jrockway

0

我尝试过这个方法(我就是那个在提到的推文中的人)。

我没有想到使用libruby的方法,但我花了相当多的时间尝试使用Ruby的FFI来包装从Haskell导出的函数,但始终无法完全链接和运行。

如果您查看Haskell的FFI示例,您会发现它们都包括一个C main()函数。由于Ruby的FFI没有(也不能有)main()函数,因此这种方法行不通。如果您尝试不使用它,您最终会遇到奇怪的链接错误。

我可以与您分享我的经验,请在freenode(cschneid)或Twitter(BlurredWeasel)上联系我。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接