我如何从Clojure中导出Java类(.jar)?
我是Clojure和Java的新手。 我有一个现有的Clojure项目,别人写道,我试图使用node-javaembedded到NodeJS中。
Clojure的
该项目定义了一个提供某些公共职能的名称空间,如下所示:
(ns my.namespace (:require ...etc...)) (defn dosomething ...) (defn dosomethingelse ...)
我用leiningen( lein jar
和lein uberjar
)build立了这个项目。
问题
node-java上的#import()文档说我需要像这样导入一个java类:
const java = require('java'); var Test = java.import('Test');
- 我怎样才能访问这些function(大概是Java类的静态方法?)
- 我接近这一切都错了吗? =)
更新
感谢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
方法。
-
使用
-
前缀来创build具有相同签名的方法的暴露版本。 它应该简单地调用你想要暴露的函数。(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] ]))
请注意,如果不希望将其作为静态方法提供,则可以select删除
#^{:static true}
。 -
在您的project.clj(假设您正在使用leiningen)中,向您的
:profiles
条目中添加提前编译指令::profiles {:uberjar {:aot :all}}
-
编译你的uberjar:
lein uberjar
生成的.jar
文件将有一个类my.classname
与一个静态方法excite
。