如何调用Java方法&从Haskell轻松实例化Java对象?

时间:2015-12-28 10:45:14

标签: java haskell

我找到了这个图书馆:https://hackage.haskell.org/package/java-bridge

根据作者的说法,支持Haskell对Java的3级绑定。正如所宣传的那样,mid level interface效果很好。但是,正如我正在使用它时,编写粘合代码开始变得重复和无聊,因为它只是以特定方式匹配类,方法和类型名称。 Here are some examples of using the mid level interface

据我了解,high level interface应该通过自动编写粘合代码来工作。 所以我试图让这项工作取得很大成功:

import Foreign.Java
import Foreign.Java.Bindings
import Data.Map as Map

main = runJava $ do
  jClasses <- reflectJavaClasses ["java.sql.DriverManager"]
  let info = Map.fromList [("java.sql.DriverManager", jClasses !! 0)]
  io $ putStrLn $ printJavaClassModule (jClasses !! 0) "DriverManager" info
  io $ putStrLn $ printJavaPackageModule "DriverManager" "DriverManager" info jClasses
  io $ putStrLn $ printJavaClassBootfile (jClasses !! 0) "DriverManager" info

其中输出以下内容:

Preprocessing executable 'exp-java' for exp-java-0.1.0.0...
[1 of 1] Compiling Main             ( main.hs, dist/build/exp-java/exp-java-tmp/Main.o )
Linking dist/build/exp-java/exp-java ...
{-# LANGUAGE Haskell2010 #-}
-- | Class @java.sql.DriverManager@
module DriverManager (
    -- * Methods
deregisterDriver,    
equals,    
getClass,    
getConnection,    
getConnection',    
getConnection'',    
getDriver,    
getDrivers,    
getLogStream,    
getLogWriter,    
getLoginTimeout,    
hashCode,    
notify,    
notifyAll,    
println,    
registerDriver,    
setLogStream,    
setLogWriter,    
setLoginTimeout,    
toString,    
wait,    
wait',    
wait'',    
    -- * Information about this class.
    info'
) where
import qualified Foreign.Java as JNI
import Foreign.Java ((-->))
import qualified Prelude as Prelude
import Prelude ((.), ($), (>>=), (>>), return)
import qualified Foreign.Java.Bindings.Support as JNIS
import Data.Functor ((<$>))


exp-java: classModImports in Foreign.Java.Bindings.Java2Haskell - class definition not found

问题

  1. 任何可能导致此问题的想法classModImports in Foreign.Java.Bindings.Java2Haskell - class definition not found请参阅下面的编辑。似乎需要使用findJavaClasses来解决此错误。

  2. 我使用的方式与预期不同吗?

  3. 我可以查看高级API的预期和工作用法示例吗?

  4. 有没有其他方法(例如不同的库)我可以(也/更容易)实现从Haskell到Java的易于使用的接口?

  5. 编辑(2015-12-28 11:42 UTC)

    我设法得到了进一步的发展,但还没有完全发挥作用:

    import Foreign.Java
    import Foreign.Java.Bindings
    import Data.Map as Map
    
    main = runJava $ do
      let target = "java.sql.DriverManager"
      deps <- findJavaClasses 21 [target]
      jClasses <- reflectJavaClasses deps
      let jClassesMap = Map.fromList $ zip deps jClasses
      let l = flip Map.lookup
      let (Just targetJClass) = jClassesMap `l` target
      io $ putStrLn $ printJavaClassModule targetJClass "DriverManager" jClassesMap
    

    哪个输出:

    {-# LANGUAGE Haskell2010 #-}
    -- | Class @java.sql.DriverManager@
    module DriverManager (
        -- * Methods
    deregisterDriver,
    equals,
    getClass,
    getConnection,
    getConnection',
    getConnection'',
    getDriver,
    getDrivers,
    getLogStream,
    getLogWriter,
    getLoginTimeout,
    hashCode,
    notify,
    notifyAll,
    println,
    registerDriver,
    setLogStream,
    setLogWriter,
    setLoginTimeout,
    toString,
    wait,
    wait',
    wait'',
        -- * Information about this class.
        info'
    ) where
    import qualified Foreign.Java as JNI
    import Foreign.Java ((-->))
    import qualified Prelude as Prelude
    import Prelude ((.), ($), (>>=), (>>), return)
    import qualified Foreign.Java.Bindings.Support as JNIS
    import Data.Functor ((<$>))
    
    
    import qualified
    
    info' = "DriverManager"
    
    -- | @static synchronized deregisterDriver(java.sql.Driver) -> void@
    deregisterDriver :: ( v1, JNIS.VoidResult void) => v1 -> JNI.Java void
    deregisterDriver a1 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "deregisterDriver" JNI.::= JNI.object "java.sql.Driver" --> JNI.void
        a1' <- Prelude.Just <$> JNI.asObject a1
        result <- JNI.callStaticMethodE method a1'
        JNIS.toVoidResult result
    -- | @virtual equals(java.lang.Object) -> boolean@
    equals :: (JNIS.BooleanResult boolean,  this,  v1) => this -> v1 -> JNI.Java boolean
    equals this a1 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getMethod` "equals" JNI.::= JNI.object "java.lang.Object" --> JNI.boolean
        this' <- JNI.asObject this
        a1' <- Prelude.Just <$> JNI.asObject a1
        result <- JNI.callMethodE method this' a1'
        JNIS.toBooleanResult result
    -- | @virtual native final getClass() -> java.lang.Class@
    getClass :: ( this, JNIS.ObjectResult (object (' v2))) => this -> JNI.Java (object (' v2))
    getClass this = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getMethod` "getClass" JNI.::= JNI.object "java.lang.Class"
        this' <- JNI.asObject this
        result <- JNI.callMethodE method this'
        JNIS.toObjectResult result
    -- | @static getConnection(java.lang.String, java.lang.String, java.lang.String) -> java.sql.Connection@
    getConnection :: ( v1,  v2,  v3, JNIS.ObjectResult (object ')) => v1 -> v2 -> v3 -> JNI.Java (object ')
    getConnection a1 a2 a3 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "getConnection" JNI.::= JNI.object "java.lang.String" --> JNI.object "java.lang.String" --> JNI.object "java.lang.String" --> JNI.object "java.sql.Connection"
        a1' <- Prelude.Just <$> JNI.asObject a1
        a2' <- Prelude.Just <$> JNI.asObject a2
        a3' <- Prelude.Just <$> JNI.asObject a3
        result <- JNI.callStaticMethodE method a1' a2' a3'
        JNIS.toObjectResult result
    -- | @static getConnection(java.lang.String, java.util.Properties) -> java.sql.Connection@
    getConnection' :: ( v1,  v2, JNIS.ObjectResult (object ')) => v1 -> v2 -> JNI.Java (object ')
    getConnection' a1 a2 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "getConnection" JNI.::= JNI.object "java.lang.String" --> JNI.object "java.util.Properties" --> JNI.object "java.sql.Connection"
        a1' <- Prelude.Just <$> JNI.asObject a1
        a2' <- Prelude.Just <$> JNI.asObject a2
        result <- JNI.callStaticMethodE method a1' a2'
        JNIS.toObjectResult result
    -- | @static getConnection(java.lang.String) -> java.sql.Connection@
    getConnection'' :: ( v1, JNIS.ObjectResult (object ')) => v1 -> JNI.Java (object ')
    getConnection'' a1 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "getConnection" JNI.::= JNI.object "java.lang.String" --> JNI.object "java.sql.Connection"
        a1' <- Prelude.Just <$> JNI.asObject a1
        result <- JNI.callStaticMethodE method a1'
        JNIS.toObjectResult result
    -- | @static getDriver(java.lang.String) -> java.sql.Driver@
    getDriver :: ( v1, JNIS.ObjectResult (object ')) => v1 -> JNI.Java (object ')
    getDriver a1 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "getDriver" JNI.::= JNI.object "java.lang.String" --> JNI.object "java.sql.Driver"
        a1' <- Prelude.Just <$> JNI.asObject a1
        result <- JNI.callStaticMethodE method a1'
        JNIS.toObjectResult result
    -- | @static getDrivers() -> java.util.Enumeration@
    getDrivers :: (JNIS.ObjectResult (object (' v2))) => JNI.Java (object (' v2))
    getDrivers = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "getDrivers" JNI.::= JNI.object "java.util.Enumeration"
        result <- JNI.callStaticMethodE method
        JNIS.toObjectResult result
    -- | @static getLogStream() -> java.io.PrintStream@
    getLogStream :: (JNIS.ObjectResult (object ')) => JNI.Java (object ')
    getLogStream = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "getLogStream" JNI.::= JNI.object "java.io.PrintStream"
        result <- JNI.callStaticMethodE method
        JNIS.toObjectResult result
    -- | @static getLogWriter() -> java.io.PrintWriter@
    getLogWriter :: (JNIS.ObjectResult (object ')) => JNI.Java (object ')
    getLogWriter = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "getLogWriter" JNI.::= JNI.object "java.io.PrintWriter"
        result <- JNI.callStaticMethodE method
        JNIS.toObjectResult result
    -- | @static getLoginTimeout() -> int@
    getLoginTimeout :: (JNIS.IntResult int) => JNI.Java int
    getLoginTimeout = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "getLoginTimeout" JNI.::= JNI.int
        result <- JNI.callStaticMethodE method
        JNIS.toIntResult result
    -- | @virtual native hashCode() -> int@
    hashCode :: (JNIS.IntResult int,  this) => this -> JNI.Java int
    hashCode this = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getMethod` "hashCode" JNI.::= JNI.int
        this' <- JNI.asObject this
        result <- JNI.callMethodE method this'
        JNIS.toIntResult result
    -- | @virtual native final notify() -> void@
    notify :: ( this, JNIS.VoidResult void) => this -> JNI.Java void
    notify this = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getMethod` "notify" JNI.::= JNI.void
        this' <- JNI.asObject this
        result <- JNI.callMethodE method this'
        JNIS.toVoidResult result
    -- | @virtual native final notifyAll() -> void@
    notifyAll :: ( this, JNIS.VoidResult void) => this -> JNI.Java void
    notifyAll this = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getMethod` "notifyAll" JNI.::= JNI.void
        this' <- JNI.asObject this
        result <- JNI.callMethodE method this'
        JNIS.toVoidResult result
    -- | @static println(java.lang.String) -> void@
    println :: ( v1, JNIS.VoidResult void) => v1 -> JNI.Java void
    println a1 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "println" JNI.::= JNI.object "java.lang.String" --> JNI.void
        a1' <- Prelude.Just <$> JNI.asObject a1
        result <- JNI.callStaticMethodE method a1'
        JNIS.toVoidResult result
    -- | @static synchronized registerDriver(java.sql.Driver) -> void@
    registerDriver :: ( v1, JNIS.VoidResult void) => v1 -> JNI.Java void
    registerDriver a1 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "registerDriver" JNI.::= JNI.object "java.sql.Driver" --> JNI.void
        a1' <- Prelude.Just <$> JNI.asObject a1
        result <- JNI.callStaticMethodE method a1'
        JNIS.toVoidResult result
    -- | @static setLogStream(java.io.PrintStream) -> void@
    setLogStream :: ( v1, JNIS.VoidResult void) => v1 -> JNI.Java void
    setLogStream a1 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "setLogStream" JNI.::= JNI.object "java.io.PrintStream" --> JNI.void
        a1' <- Prelude.Just <$> JNI.asObject a1
        result <- JNI.callStaticMethodE method a1'
        JNIS.toVoidResult result
    -- | @static setLogWriter(java.io.PrintWriter) -> void@
    setLogWriter :: ( v1, JNIS.VoidResult void) => v1 -> JNI.Java void
    setLogWriter a1 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "setLogWriter" JNI.::= JNI.object "java.io.PrintWriter" --> JNI.void
        a1' <- Prelude.Just <$> JNI.asObject a1
        result <- JNI.callStaticMethodE method a1'
        JNIS.toVoidResult result
    -- | @static setLoginTimeout(int) -> void@
    setLoginTimeout :: (JNIS.JInt v1, JNIS.VoidResult void) => v1 -> JNI.Java void
    setLoginTimeout a1 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getStaticMethod` "setLoginTimeout" JNI.::= JNI.int --> JNI.void
        a1' <- JNIS.toInt a1
        result <- JNI.callStaticMethodE method a1'
        JNIS.toVoidResult result
    -- | @virtual toString() -> java.lang.String@
    toString :: ( this, JNIS.ObjectResult (object ')) => this -> JNI.Java (object ')
    toString this = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getMethod` "toString" JNI.::= JNI.object "java.lang.String"
        this' <- JNI.asObject this
        result <- JNI.callMethodE method this'
        JNIS.toObjectResult result
    -- | @virtual final wait(long, int) -> void@
    wait :: ( this, JNIS.JLong v1, JNIS.JInt v2, JNIS.VoidResult void) => this -> v1 -> v2 -> JNI.Java void
    wait this a1 a2 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getMethod` "wait" JNI.::= JNI.long --> JNI.int --> JNI.void
        this' <- JNI.asObject this
        a1' <- JNIS.toLong a1
        a2' <- JNIS.toInt a2
        result <- JNI.callMethodE method this' a1' a2'
        JNIS.toVoidResult result
    -- | @virtual native final wait(long) -> void@
    wait' :: ( this, JNIS.JLong v1, JNIS.VoidResult void) => this -> v1 -> JNI.Java void
    wait' this a1 = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getMethod` "wait" JNI.::= JNI.long --> JNI.void
        this' <- JNI.asObject this
        a1' <- JNIS.toLong a1
        result <- JNI.callMethodE method this' a1'
        JNIS.toVoidResult result
    -- | @virtual final wait() -> void@
    wait'' :: ( this, JNIS.VoidResult void) => this -> JNI.Java void
    wait'' this = do
        (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
        (Prelude.Just method) <- clazz `JNI.getMethod` "wait" JNI.::= JNI.void
        this' <- JNI.asObject this
        result <- JNI.callMethodE method this'
        JNIS.toVoidResult result
    

    现在这已经相当接近,但是即使我尝试手动修补输出源,我也不会用GHC 7.8.4进行编译。

    1. 顶部有一个空的import qualified,导致语法错误。所以我试着通过评论来禁用它。

    2. 然后有很多错误消息指向类型声明的各个部分,所以我也对它们进行了评论,希望GHC可能会推断出一些明智的东西。至少在我试图让它发挥作用之前。

    3. 然后我收到此错误:

      Preprocessing executable 'exp-java' for exp-java-0.1.0.0...
      [1 of 2] Compiling DriverManager    ( DriverManager.hs, dist/build/exp-java/exp-java-tmp/DriverManager.o )
      
      DriverManager.hs:109:5:
          No instance for (JNIS.ObjectResult b3)
            arising from a use of ‘JNIS.toObjectResult’
          The type variable ‘b3’ is ambiguous
          Relevant bindings include
            getDrivers :: JNI.Java b3 (bound at DriverManager.hs:105:1)
          Note: there are several potential instances:
            instance JNIS.UnsafeCast a =>
                     JNIS.ObjectResult (Prelude.Either JNI.JThrowable (Prelude.Maybe a))
              -- Defined in ‘Foreign.Java.Bindings.Support’
            instance JNIS.UnsafeCast a =>
                     JNIS.ObjectResult (Prelude.Either (Prelude.Maybe JNI.JThrowable) a)
              -- Defined in ‘Foreign.Java.Bindings.Support’
            instance JNIS.UnsafeCast a => JNIS.ObjectResult (Prelude.Maybe a)
              -- Defined in ‘Foreign.Java.Bindings.Support’
            ...plus two others
          In a stmt of a 'do' block: JNIS.toObjectResult result
          In the expression:
            do { (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager";
                 (Prelude.Just method) <- clazz
                                          `JNI.getStaticMethod`
                                            "getDrivers" JNI.::= JNI.object "java.util.Enumeration";
                 result <- JNI.callStaticMethodE method;
                 JNIS.toObjectResult result }
          In an equation for ‘getDrivers’:
              getDrivers
                = do { (Prelude.Just clazz) <- JNI.getClass
                                                 "java.sql.DriverManager";
                       (Prelude.Just method) <- clazz
                                                `JNI.getStaticMethod`
                                                  "getDrivers" JNI.::= JNI.object "java.util.Enumeration";
                       result <- JNI.callStaticMethodE method;
                       .... }
      
    4. 我还不确定如何解决。有什么想法吗?

      我的问题2..4在原始问题的最后,就在编辑之前,仍然有效。

0 个答案:

没有答案