自从发表这一答复以来,一些可用的工具发生了变化。在最初的答案之后,有一个更新,包括有关如何用当前工具构建示例的信息。
它并不像编译JAR和调用内部方法那样简单。不过,似乎确实有一些小窍门可以让这一切发挥作用。下面是一个可以编译到JAR中的简单Clojure文件的示例:(ns com.domain.tiny (:gen-class
:name com.domain.tiny :methods [#^{:static true} [binomial [int int] double]]))(defn binomial
"Calculate the binomial coefficient."
[n k]
(let [a (inc n)]
(loop [b 1
c 1]
(if (> b k)
c (recur (inc b) (* (/ (- a b) b) c))))))(defn -binomial "A Java-callable wrapper around the 'binomial' function."
[n k]
(binomial n k))(defn -main []
(println (str "(binomial 5 3): " (binomial 5 3)))
(println (str "(binomial 10042 111): " (binomial 10042 111))))
如果你运行它,你应该看到这样的东西:(binomial 5 3): 10(binomial 10042 111): 49068389575068144946633777...
下面是一个Java程序,它调用-binomial函数中的tiny.jar.import com.domain.tiny;public class Main {
public static void main(String[] args) {
System.out.println("(binomial 5 3): " + tiny.binomial(5, 3));
System.out.println("(binomial 10042, 111): " + tiny.binomial(10042, 111));
}}
它的输出是:(binomial 5 3): 10.0(binomial 10042, 111): 4.9068389575068143E263
第一个魔法是使用:methods关键字中的gen-class声明。这似乎是允许您访问Clojure函数(类似于Java中的静态方法)所必需的。
第二件事是创建一个可以由Java调用的包装器函数。注意,第二个版本的-binomial前面有个破折号。
当然,Clojure JAR本身必须在类路径上。这个例子使用了Clojure-1.1.0 JAR。
更新使用以下工具重新测试了这个答案:Clojure 1.5.1
莱宁根2.1.3
JDK 1.7.0更新25
克洛尔部分
首先,使用Leiningen创建一个项目和相关目录结构:C:\projects>lein new com.domain.tiny
现在,切换到项目目录。C:\projects>cd com.domain.tiny
在项目目录中,打开project.clj文件并编辑它,以便内容如下所示。(defproject com.domain.tiny "0.1.0-SNAPSHOT"
:description "An example of stand alone Clojure-Java interop"
:url "http://clarkonium.net/2013/06/java-clojure-interop-an-update/"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"]]
:aot :all :main com.domain.tiny)
现在,确保所有依赖项(Clojure)都可用。C:\projects\com.domain.tiny>lein deps
此时您可能会看到一条关于下载Clojure JAR的消息。
现在编辑Clojure文件C:\projects\com.domain.tiny\src\com\domain\tiny.clj这样,它就包含了原来答案中显示的Clojure程序。(此文件是在Leiningen创建项目时创建的。)
这里的许多神奇之处在于名称空间声明。这个:gen-class告诉系统创建一个名为com.domain.tiny使用一个名为binomial一个函数,使用两个整数参数并返回一个Double。有两个类似命名的函数binomial,一个传统的Clojure函数,以及-binomial以及从Java访问的包装器。注意函数名称中的连字符-binomial..默认前缀是连字符,但如果需要,可以更改为其他前缀。这个-main函数只对二项式函数进行几次调用,以确保我们得到了正确的结果。为此,编译类并运行程序。C:\projects\com.domain.tiny>lein run
您应该看到原始答案中显示的输出。
现在把它装在一个罐子里,放在一个方便的地方。在那里也复制Clojure的罐子。C:\projects\com.domain.tiny>lein jarCreated C:\projects\com.domain.tiny\target\com.domain.tiny-0.1.0-SNAPSHOT.jar
C:\projects\com.domain.tiny>mkdir \target\lib
C:\projects\com.domain.tiny>copy target\com.domain.tiny-0.1.0-SNAPSHOT.jar target\lib\
1 file(s) copied.C:\projects\com.domain.tiny>copy "C:\clojure-1.5.1.jar" target\lib\ 1 file(s) copied.
Java部分
莱宁根有一个内置的任务,lein-javac,这应该有助于Java编译。不幸的是,它似乎在2.1.3版本中被破坏了。它找不到已安装的JDK,也找不到Maven存储库。两者的路径都在我的系统中嵌入了空间。我想这就是问题所在。任何JavaIDE也可以处理编译和打包。但对于这篇文章,我们是老生常谈,在命令行做这件事。
首先创建文件Main.java内容显示在原来的答案中。
编译java部件javac -g -cp target\com.domain.tiny-0.1.0-SNAPSHOT.jar -d target\src\com\domain\Main.java
现在创建一个文件,其中包含一些要添加到我们要构建的JAR中的元信息。在……里面Manifest.txt,添加以下文本Class-Path: lib\com.domain.tiny-0.1.0-SNAPSHOT.jar lib\clojure-1.5.1.jarMain-Class: Main
现在,将其打包到一个大JAR文件中,包括我们的Clojure程序和Clojure JAR。C:\projects\com.domain.tiny\target>jar cfm Interop.jar Manifest.txt Main.class lib\com.domain.tiny-0.1.0-SNAPSHOT.jar lib\clojure-1.5.1.jar
要运行该程序:C:\projects\com.domain.tiny\target>java -jar Interop.jar(binomial 5 3): 10.0(binomial 10042, 111): 4.9068389575068143E263
输出与Clojure单独生成的输出本质上是相同的,但结果已经转换为Java双重。
如前所述,JavaIDE可能会处理混乱的编译参数和打包。