如何从Clojure导出Java类(.jar)?

如何从Clojure导出Java类(.jar)?,java,node.js,clojure,node-java,Java,Node.js,Clojure,Node Java,我在Clojure和Java方面比较新手。我有一个别人写的Clojure项目,我正试图用它嵌入NodeJS Clojure 项目定义了一个命名空间,该命名空间提供某些公共函数,如下所示: (ns my.namespace (:require ...etc...)) (defn dosomething ...) (defn dosomethingelse ...) 我已经和leiningen一起构建了这个项目(LeinJar和LeinUberJar) 问题 on node java说我需要

我在Clojure和Java方面比较新手。我有一个别人写的Clojure项目,我正试图用它嵌入NodeJS

Clojure

项目定义了一个命名空间,该命名空间提供某些公共函数,如下所示:

(ns my.namespace
  (:require ...etc...))

(defn dosomething ...)
(defn dosomethingelse ...)
我已经和leiningen一起构建了这个项目(
LeinJar
LeinUberJar

问题

on node java说我需要像这样导入一个java类:

const java = require('java');
var Test = java.import('Test');
  • 如何访问这些函数(可能是Java类静态方法?)
  • 我是不是完全错了 更新

    多亏了Magos(下面的答案),我取得了一些进步。事实证明,我可以在
    (ns…
    范围中使用
    (:gen class:name my.name)
    来告诉它生成一个类。如果我向project.clj添加配置文件,如下所示:

    ...
    :profiles {
      ...
      :uberjar {:aot :all}
    }
    ...
    

    它将被编译,我现在可以在Node中看到这个类。不过,我还没有弄清楚如何导出这些方法。现在正在做那部分。

    既然是其他人写的Clojure,我想你无法控制它。从另一种JVM语言使用Clojure代码的推荐方法是从类引导。这个类允许您从Clojure解析变量,通过解析和调用其他核心Clojure函数,您可以加载自己的代码。根据您的示例,它可能如下所示:

    const java = require('java');
    var clojure = java.import('clojure.java.api.Clojure');
    IFn require = clojure.var("clojure.core", "require");
    require.invoke(clojure.read("my.namespace"));
    IFn doSomething = clojure.var("my.namespace","dosomething");
    //doSomething.invoke(....
    
    如果您确实控制Clojure

    注意:我是通过马戈斯的回答和克拉塔克对这个问题的评论得出这个结论的

    下面是如何操作的简单说明。假设您有以下(简单的)clojure代码:

    (ns my.namespace
      "a trivial library"
      (:require [something.else :as other]))
    
    (defn excite
      "make things more exciting"
      [mystr]
      (print-str mystr "!"))
    
    使用以下步骤公开
    excite
    方法

  • 通过使用
    -
    前缀创建具有相同签名的方法的公开版本。它应该只调用您希望公开的函数

    (defn -excite [mystr] (excite mystr))
    
  • (ns…
    中声明要生成类并导出方法

    (ns my.namespace
      "a trivial library"
      (:require [something.else :as other])
      (:gen-class
        :name my.classname
        :methods [
          ;   metadata      mtd.name signature  returns
          #^{:static true} [excite   [String]   void]
        ]))
    
    请注意,如果不希望将其作为静态方法提供,可以选择删除
    #^{:static true}

  • 在project.clj(假设您使用的是leiningen)中,向
    :profiles
    条目添加提前编译说明:

    :profiles {:uberjar {:aot :all}}
    
  • 编译您的uberjar:

    lein uberjar
    

  • 生成的
    .jar
    文件将有一个类
    my.classname
    ,带有一个静态方法
    excite

    ,我认为从Java项目导入.jar和从Clojure项目导入.jar之间没有什么区别。您能够从Java项目导入任何.jar吗?Clojure因素可能是一个误导。@Carcigenicate在我添加jar时没有给出错误。但更重要的一点(我认为)是,我不知道生成的.jar中的类是什么。我能找出罐子里有哪些类吗?我不知道。我会在一个好的IDE中打开它,尝试导入它,然后看看自动完成是否会给你任何提示。我希望它们都在
    测试下
    ,并使用JS的成员访问操作符进行访问。如果你找不到深入的指南,只是到处玩可能会很有用。如果你只想从clojure jar导出一些静态函数,我的一个老答案()说明了如何这样做,但Magos讨论的方法更一般。要查看jar文件中有哪些类,您可以使用类似WinZip的东西打开jar,因为jar本质上就是zip文件。谢谢,这是一个很好的起点。我确实控制了这个软件,但是团队的一位前成员写了它,我现在无法与他联系。