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

我是Clojure和Java的新手。 我有一个现有的Clojure项目,别人写道,我试图使用node-javaembedded到NodeJS中。

Clojure的

该项目定义了一个提供某些公共职能的名称空间,如下所示:

(ns my.namespace (:require ...etc...)) (defn dosomething ...) (defn dosomethingelse ...) 

我用leiningen( lein jarlein uberjar )build立了这个项目。

问题

node-java上的#import()文档说我需要像这样导入一个java类:

 const java = require('java'); var Test = java.import('Test'); 
  1. 我怎样才能访问这些function(大概是Java类的静态方法?)
  2. 我接近这一切都错了吗? =)

更新

感谢Magos(下面的答案),我做了更多的进展。 原来我可以在(ns ...)范围内使用(:gen-class :name my.name)来告诉它生成一个类。 如果我像这样添加一个configuration文件到project.clj:

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

它会编译,我现在可以在Node中看到类。 不过,我仍然没有想出如何导出这些方法。 现在就在这个部分工作。

由于别人写了Clojure,我认为你不能控制它。 从另一个JVM语言使用Clojure代码的推荐方法是从clojure.java.api.Clojure类引导。 这个类允许你从Clojure中parsingVars,通过parsing和调用其他的核心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, :gen-class允许你将函数导出为命名空间生成的类的方法 。

注:我是通过Magos的回答和clartaq对这个问题的评论的结合来达到这个目的的。

这里是如何做到这一点的简单说明。 假设你有这个(简单的)clojure代码:

 (ns my.namespace "a trivial library" (:require [something.else :as other])) (defn excite "make things more exciting" [mystr] (print-str mystr "!")) 

使用这些步骤来公开excite方法。

  1. 使用-前缀来创build具有相同签名的方法的暴露版本。 它应该简单地调用你想要暴露的函数。

     (defn -excite [mystr] (excite mystr)) 
  2. (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] ])) 

    请注意,如果不希望将其作为静态方法提供,则可以select删除#^{:static true}

  3. 在您的project.clj(假设您正在使用leiningen)中,向您的:profiles条目中添加提前编译指令:

     :profiles {:uberjar {:aot :all}} 
  4. 编译你的uberjar:

     lein uberjar 

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