Java和Haskell之间的通信 [英] Communication between Java and Haskell

查看:126
本文介绍了Java和Haskell之间的通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我搜索了一些答案,可以通过GCJNI(现在网站已关闭)和LambdaVM完成Java与Haskell之间的通信。要使用LambdaVM / GCJNI,是否需要下载任何构建工具?我在哪里可以了解更多关于他们的信息,因为我没有在网上找到很多资源?

我想开发一个在Java和Haskell之间进行通信的应用程序(我将从Java的输入中将其传递给Haskell并在那里处理并返回结果Java)。这是我想要做的。请帮助我...

解决方案

从C调用Haskell看起来很容易,因此也可以通过 JavaCPP 的。例如,要从示例代码 Safe.hs 中调用 fibonacci_hs()函数:

  { - #LANGUAGE ForeignFunctionInterface# - } 

模块安全其中

导入Foreign.C。类型

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

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

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

我们可以用Java这种方式完成它:

  import org.bytedeco.javacpp。*; 
import org.bytedeco.javacpp.annotation。*;

@Platform(include = {< HsFFI.h>,Safe_stub.h})
public class Safe {
static {Loader.load(); }
public static native void hs_init(int [] argc,@Cast(char ***)@ByPtrPtr PointerPointer argv);
public static native int fibonacci_hs(int i);
public static void main(String [] args){
hs_init(null,null);
int i = fibonacci_hs(42);
System.out.println(Fibonacci:+ i);


$ / code>

在Linux下,编译过程如下所示: / p>

  $ ghc -fPIC -dynamic -c -O Safe.hs 
$ javac -cp javacpp.jar Safe.java
$ java -jar javacpp.jar -Dplatform.compiler = ghc -Dplatform.compiler.output = - optc-O3 -Wall Safe.o -dynamic -fPIC -shared -lstdc ++ -lHSrts-ghc7.6.3 -o -Dplatform.linkpath.prefix2 = - optl -Wl,-rpath,Safe

程序通常使用通常的 java 命令运行:

  $ java -cp javacpp.jar :. Safe 
Fibonacci:267914296



编辑
strong>:我冒昧地做了一些调用开销的微观基准。使用以下C头文件 Safe.h

  inline int fibonacci_c (int n){
return n< 2? n:fibonacci_c(n - 1)+ fibonacci_c(n - 2);
}

以下Java类:

  import org.bytedeco.javacpp。*; 
import org.bytedeco.javacpp.annotation。*;
$ b @Platform(include = {< HsFFI.h>,Safe_stub.h,Safe.h})
public class Safe {
static { Loader.load方法(); }
public static native void hs_init(int [] argc,@Cast(char ***)@ByPtrPtr PointerPointer argv);
public static native int fibonacci_hs(int i);
public static native int fibonacci_c(int n);
public static int fibonacci(int n){
return n< 2? n:斐波纳契(n - 1)+斐波纳契(n - 2);
}
public static void main(String [] args){
hs_init(null,null);

for(int i = 0; i <1000000; i ++){
fibonacci_hs(0);
fibonacci_c(0);
fibonacci(0);
}
long t1 = System.nanoTime();
for(int i = 0; i< 1000000; i ++){
fibonacci_hs(0);
}
long t2 = System.nanoTime();
for(int i = 0; i< 1000000; i ++){
fibonacci_c(0);
}
long t3 = System.nanoTime();
for(int i = 0; i< 1000000; i ++){
fibonacci(0);
}
long t4 = System.nanoTime();
System.out.println(fibonacci_hs(0):+(t2 - t1)/ 1000000 +ns);
System.out.println(fibonacci_c(0):+(t3 - t2)/ 1000000 +ns);
System.out.println(fibonacci(0):+(t4 - t3)/ 1000000 +ns);
}
}

用Intel Core i7-3632QM CPU @ 2.20GHz,Fedora 20 x86_64,GCC 4.8.3,GHC 7.6.3和OpenJDK 8:

  fibonacci_hs(0): 200 ns 
fibonacci_c(0):9 ns
fibonacci(0):2 ns



平心而论,我应该提到将调用到 JVM也是相当昂贵的...





更新最近对JavaCPP进行的更改用户现在可以通过C / C ++中的名称访问回调函数(指针),从而可以轻松地从Haskell调用JVM。例如,根据 wiki页面上有关Haskell的FFI 的信息,并将下列代码放入 Main.hs

  { - #LANGUAGE ForeignFunctionInterface# - } 
模块Main其中

导入Foreign.C - 获取C类型
导入Foreign.Ptr(Ptr,nullPtr)

- 不纯函数
foreign import ccallJavaCPP_initc_javacpp_init :: CInt - > Ptr(Ptr CString) - > IO()
javacpp_init :: IO()
javacpp_init = c_javacpp_init 0 nullPtr

- 纯函数
外部导入ccallfibonaccic_fibonacci :: CInt - > ; CInt
fibonacci :: Int - > Int
fibonacci i = fromIntegral(c_fibonacci(fromIntegral i))

main = do
javacpp_init
print $ fibonacci 42

和Java中这样定义的 fibonacci 函数:

  import org.bytedeco.javacpp。*; 
import org.bytedeco.javacpp.annotation。*;

@Platform
public class Main {
public static class Fibonacci extends FunctionPointer {
public @Name(fibonacci)int call(int n){
return n < 2? n:通话(n - 1)+通话(n - 2);



$ / code $ / pre

我们可能在Linux x86_64下构建类似于:

  $ javac -cp javacpp.jar Main.java 
$ java -jar javacpp.jar Main -header
$ ghc --make Main.hs linux-x86_64 / libjniMain.so

并且程序正确地执行这个输出:

  $ ./Main 
267914296


I googled and got some answers that communication between Java and Haskell can be done by GCJNI(Now the site is down) and LambdaVM.. To use the LambdaVM/GCJNI, whether I need to download any build tools? Where can I know more about them, since I don't find much resources on online?

I want to develop an application that communicates between Java and Haskell(Where I will get the input from Java pass it to the Haskell and process there and return the result back to Java).This is what I want to do. Please help me...

解决方案

Calling Haskell from C appears quite easy, and thus can also be easily called from Java with JavaCPP. For example, to call the fibonacci_hs() function from the sample code Safe.hs:

{-# LANGUAGE ForeignFunctionInterface #-}

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

we can do it this way from Java:

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;

@Platform(include={"<HsFFI.h>","Safe_stub.h"})
public class Safe {
    static { Loader.load(); }
    public static native void hs_init(int[] argc, @Cast("char***") @ByPtrPtr PointerPointer argv);
    public static native int fibonacci_hs(int i);
    public static void main(String[] args) {
        hs_init(null, null);
        int i = fibonacci_hs(42);
        System.out.println("Fibonacci: " + i);
    }
}

Under Linux, the compilation procedure looks like this:

$ ghc -fPIC -dynamic -c -O Safe.hs
$ javac -cp javacpp.jar Safe.java
$ java -jar javacpp.jar -Dplatform.compiler=ghc -Dplatform.compiler.output="-optc-O3 -Wall Safe.o -dynamic -fPIC -shared -lstdc++ -lHSrts-ghc7.6.3 -o " -Dplatform.linkpath.prefix2="-optl -Wl,-rpath," Safe

And the program runs normally with the usual java command:

$ java -cp javacpp.jar:. Safe
Fibonacci: 267914296


Edit: I have taken the liberty to do some microbenchmarking of the calling overhead. With the following C header file Safe.h:

inline int fibonacci_c(int n) {
    return n < 2 ? n : fibonacci_c(n - 1) + fibonacci_c(n - 2);
}

the following Java class:

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;

@Platform(include={"<HsFFI.h>","Safe_stub.h", "Safe.h"})
public class Safe {
    static { Loader.load(); }
    public static native void hs_init(int[] argc, @Cast("char***") @ByPtrPtr PointerPointer argv);
    public static native int fibonacci_hs(int i);
    public static native int fibonacci_c(int n);
    public static int fibonacci(int n) {
        return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
    }
    public static void main(String[] args) {
        hs_init(null, null);

        for (int i = 0; i < 1000000; i++) {
            fibonacci_hs(0);
            fibonacci_c(0);
            fibonacci(0);
        }
        long t1 = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            fibonacci_hs(0);
        }
        long t2 = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            fibonacci_c(0);
        }
        long t3 = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            fibonacci(0);
        }
        long t4 = System.nanoTime();
        System.out.println("fibonacci_hs(0): " + (t2 - t1)/1000000 + " ns");
        System.out.println("fibonacci_c(0): "  + (t3 - t2)/1000000 + " ns");
        System.out.println("fibonacci(0): "    + (t4 - t3)/1000000 + " ns");
    }
}

outputs this with an Intel Core i7-3632QM CPU @ 2.20GHz, Fedora 20 x86_64, GCC 4.8.3, GHC 7.6.3, and OpenJDK 8:

fibonacci_hs(0): 200 ns
fibonacci_c(0): 9 ns
fibonacci(0): 2 ns

In all fairness, I should mention that it is also pretty expensive to call into the JVM as well...


Update: With recent changes to JavaCPP, users can now access callback function (pointers) by name from C/C++, making it possible to call into the JVM from Haskell easily. For example, based on information found on a wiki page regarding Haskell's FFI, with the following code placed in Main.hs:

{-# LANGUAGE ForeignFunctionInterface #-}
module Main where

import Foreign.C -- get the C types
import Foreign.Ptr (Ptr,nullPtr)

-- impure function
foreign import ccall "JavaCPP_init" c_javacpp_init :: CInt -> Ptr (Ptr CString) -> IO ()
javacpp_init :: IO ()
javacpp_init = c_javacpp_init 0 nullPtr

-- pure function
foreign import ccall "fibonacci" c_fibonacci :: CInt -> CInt
fibonacci :: Int -> Int
fibonacci i = fromIntegral (c_fibonacci (fromIntegral i))

main = do
  javacpp_init
  print $ fibonacci 42

and a fibonacci function defined in Java this way:

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;

@Platform
public class Main {
    public static class Fibonacci extends FunctionPointer {
        public @Name("fibonacci") int call(int n) {
            return n < 2 ? n : call(n - 1) + call(n - 2);
        }
    }
}

we may build under Linux x86_64 with something like:

$ javac -cp javacpp.jar Main.java
$ java -jar javacpp.jar Main -header
$ ghc --make Main.hs linux-x86_64/libjniMain.so

and the program executes correctly giving this output:

$ ./Main
267914296

这篇关于Java和Haskell之间的通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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