Haskell 通过 FFI 与 Ruby 绑定?

发布于 2024-07-15 11:23:31 字数 123 浏览 8 评论 0原文

由于 ruby​​ 和 Haskell 都支持 FFI,

  • 是否可以通过 FFI 从 ruby​​ 调用 Haskell 代码?
  • Ruby 中有 Haskell 绑定吗?

Since both ruby and Haskell supports FFI,

  • Is it possible to call Haskell code from ruby, may be through FFI ?
  • Is there any Haskell binding in Ruby ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

七堇年 2024-07-22 11:23:31

我对这个讨论有点晚了,但我目前正在编写 Ruby 和 Haskell 之间的桥梁。 它位于 http://github.com/mwotton/Hubris - 这是一个在 C 级别工作的绑定。 不过,仍处于开发的早期阶段。

I'm a bit late to this discussion, but I'm currently writing a bridge between Ruby and Haskell. It's at http://github.com/mwotton/Hubris - it's a binding that works at the C level. Still at a very early stage of development, though.

长亭外,古道边 2024-07-22 11:23:31

GHC 6.12.1 支持在 Linux 上构建动态库。 类似

Example.hswrapper.cscript.rbMakefile

{-# 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

命令

#include <stdlib.h>

#include "HsFFI.h"

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

void
example_exit (void)
{
  hs_exit ();
}

运行

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

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

GHC 6.12.1 supports building dynamic libraries on Linux. Try something like:

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

Commands to run

make
ruby script.rb
梦毁影碎の 2024-07-22 11:23:31

我以前没见过这样做,但这是可能的。

  • 使用 Haskell 的 FFI 来包装 libruby。 您的主要可执行文件将用 Haskell 编写,它将调用 ruby​​_init() 和相关函数,以便在进程中运行 Ruby 解释器。 不过,这确实允许您运行任意 Ruby 代码。
  • 使用 Ruby 的 FFI 包装 GHC 模块 作为一个图书馆。 您的 Ruby 脚本必须调用 hs_init(),并且只能访问外部导出函数。

您需要编写粘合代码(其中一些是用 C 语言编写的)才能使这两个选项中的任何一个起作用。

  • 在单独的进程中运行 Ruby 和 Haskell,使用一些 IPC 在它们之间进行通信。 也许 XML-RPC (Haskell/Ruby),或 JSON (Haskell/Ruby) 通过套接字,甚至可能只是使用您自己的自定义协议进行管道。

我不知道你的要求是什么,但这就是我想要的——它要容易得多。

I haven't seen it done before, but it's possible.

  • Use Haskell's FFI to wrap libruby. Your main executable will be written in Haskell, which will call ruby_init() and related functions, in order to run the Ruby interpreter in-process. This does allow you to run arbitrary Ruby code, though.
  • Use Ruby's FFI to wrap a GHC module as a library. Your Ruby script must call hs_init(), and can only access foreign exported functions.

You'll need to write glue code, some in C, to get either of those two options working.

  • Run Ruby and Haskell in separate processes, using some IPC to communicate between them. Maybe XML-RPC (Haskell/Ruby), or JSON (Haskell/Ruby) over sockets, or maybe even just pipes with your own custom protocol.

I don't know what your requirements are, but this is what I'd go for -- it's a lot easier.

回眸一笑 2024-07-22 11:23:31

我不确定 Haskell 方面如何,但这是来自 Mountain West Ruby Conf 09 的一段很酷的视频,介绍了如何使用 Ruby 的 FFI。 它看起来是一个非常好的界面。

http://mwrc2009.confreaks.com/ 13-mar-2009-16-10-ffi-jeremy-hinegardner.html

I am not sure about the Haskell side, but here is a cool video from Mountain West Ruby Conf 09 about working with FFI from Ruby. It looks like a pretty nice interface.

http://mwrc2009.confreaks.com/13-mar-2009-16-10-ffi-jeremy-hinegardner.html

乖乖 2024-07-22 11:23:31

@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 或 ruby​​ 中的其他科学库
  • GNU 科学库的 Ruby 绑定
  • 或 go ruby​​ 1.9 和使用 YARV2LLVM 将计算逻辑 JIT 到 LLVM 中以加快执行速度。

有人想吗?

@ephemient, I am actually looking for someways to use Ruby (high level + dynamic) to be the main controller logic and invoking haskell for large amount of data crunching (functional + speed)

I think native binding is close to non-existence, apart from this tweet http://twitter.com/BlurredWeasel/status/1321484127

Using JSON RPC will be probably the easiest way to implement where there is a thin wrapper in ruby to (method_missing) to invoke haskell over JSON/Socket.

JSON has the advantage of being able to easily map primitives to native types between various languages..

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

Other alternative for fast number crunching in ruby (+ functional style)

  • NArray or other scientific library in ruby
  • Ruby binding of GNU Scientific Library
  • or go ruby 1.9 and use YARV2LLVM to JIT the calculation logic into LLVM for faster execution.

Thoughts anyone?

甜味拾荒者 2024-07-22 11:23:31

我确实尝试过这一点(我就是上述推文中的那个人)。

我没有想到 libruby 方法,但我花了相当多的时间尝试使用 ruby​​ 的 FFI 来包装从 haskell 导出的函数,但永远无法完全将其全部链接并运行。

如果您查看 haskell 的 FFI 示例,您会发现它们都包含 C main() 函数。 由于 ruby​​ 的 FFI 没有(也不可能有) main(),所以这是行不通的。 如果你尝试不这样做,你最终会遇到奇怪的链接错误。

我可以与您分享我所拥有的内容,请在 freenode (cschneid) 或 twitter (BlurredWeasel) 上 ping 我。

I tried exactly this (I'm the one from the mentioned tweet).

I didn't think of the libruby approach, but I spent a fair amount trying to use ruby's FFI to wrap an exported function from haskell, and could never quite get it to all link and run.

If you look at haskell's FFI examples, you'll see that they all include a C main() function. Since ruby's FFI doesn't have (and can't have) a main(), that won't work. If you try without that, you end up with weird link errors.

I can share what I have with you, ping me on freenode (cschneid), or on twitter (BlurredWeasel).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文