Clojure: gen-class 并在 java 中导入;包,路径,class路径
Clojure: gen-class and import it in java; packages, paths, classpaths
我想调用从 Java 编译为 class 的 Clojure 代码。
Clojure class:
(ns clj.core)
(gen-class
:name de.wt.TestClj
:state state
:init init
:prefix "-"
:main false
:methods [[setValue [String] void]
[getValue [] String]])
(defn -init []
[[] (atom {:value ""})])
(defn -setValue [this val]
(swap! (.state this) assoc :value val))
(defn -getValue [this]
(@(.state this) :value))
使用 lein uberjar
编译并将输出 -standalone.jar 复制到子目录 de/wt
.
下的 Java 项目中
.java 文件:
import de.wt.TestClj;
class CljTest {
public static void main(String args[]) {
TestClj test = new TestClj();
System.out.println("Pre: " + test.getValue());
test.setValue("foo");
System.out.println("Post: " + test.getValue());
}
}
现在当我尝试编译时
~/testbed/cljava/java % tree [1 14:44:53]
.
├── CljTest.java
├── de
│ └── wt
│ └── TestClj.jar
└── TestClj.jar
2 directories, 3 files
~/testbed/cljava/java % javac -cp ./:./de/wt/TestClj.jar CljTest.java
CljTest.java:1: error: package de.wt does not exist
import de.wt.TestClj;
^
CljTest.java:5: error: cannot find symbol
TestClj test = new TestClj();
^
symbol: class TestClj
location: class CljTest
CljTest.java:5: error: cannot find symbol
TestClj test = new TestClj();
^
symbol: class TestClj
location: class CljTest
3 errors
命名files/packages、创建目录和设置class路径需要遵循什么方案?
您应该能够在您的 jar 中看到 java class,类似于:
$ jar tvf target/default-0.1.0-SNAPSHOT-standalone.jar | grep TestClj
2090 Mon Jan 01 18:43:12 CET 2018 de/wt/TestClj.class
如果没有,请确保您的 project.clj 中有一个 :aot
(提前编译)指令:
(defproject default "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:aot [clj.core]
:dependencies [[org.clojure/clojure "1.7.0"]])
一旦您在 jar 中看到 .class
文件,在您的 classpath 中看到该 jar,您在 Java 代码中的导入应该可以正常工作。
如文档中所述 (https://clojure.org/reference/compilation):
Clojure compiles all code you load on-the-fly into JVM bytecode, but sometimes it is advantageous to compile ahead-of-time (AOT). Some reasons to use AOT compilation are:
To deliver your application without source
To speed up application startup
To generate named classes for use by Java
To create an application that does not need runtime bytecode generation and custom classloaders
另见 http://clojure-doc.org/articles/language/interop.html:
AOT
gen-class
requires ahead-of-time (AOT) compilation. It means that before using the classes defined with gen-class
, the Clojure compiler needs to produce .class files from gen-class
definitions.
我想调用从 Java 编译为 class 的 Clojure 代码。
Clojure class:
(ns clj.core)
(gen-class
:name de.wt.TestClj
:state state
:init init
:prefix "-"
:main false
:methods [[setValue [String] void]
[getValue [] String]])
(defn -init []
[[] (atom {:value ""})])
(defn -setValue [this val]
(swap! (.state this) assoc :value val))
(defn -getValue [this]
(@(.state this) :value))
使用 lein uberjar
编译并将输出 -standalone.jar 复制到子目录 de/wt
.
.java 文件:
import de.wt.TestClj;
class CljTest {
public static void main(String args[]) {
TestClj test = new TestClj();
System.out.println("Pre: " + test.getValue());
test.setValue("foo");
System.out.println("Post: " + test.getValue());
}
}
现在当我尝试编译时
~/testbed/cljava/java % tree [1 14:44:53]
.
├── CljTest.java
├── de
│ └── wt
│ └── TestClj.jar
└── TestClj.jar
2 directories, 3 files
~/testbed/cljava/java % javac -cp ./:./de/wt/TestClj.jar CljTest.java
CljTest.java:1: error: package de.wt does not exist
import de.wt.TestClj;
^
CljTest.java:5: error: cannot find symbol
TestClj test = new TestClj();
^
symbol: class TestClj
location: class CljTest
CljTest.java:5: error: cannot find symbol
TestClj test = new TestClj();
^
symbol: class TestClj
location: class CljTest
3 errors
命名files/packages、创建目录和设置class路径需要遵循什么方案?
您应该能够在您的 jar 中看到 java class,类似于:
$ jar tvf target/default-0.1.0-SNAPSHOT-standalone.jar | grep TestClj
2090 Mon Jan 01 18:43:12 CET 2018 de/wt/TestClj.class
如果没有,请确保您的 project.clj 中有一个 :aot
(提前编译)指令:
(defproject default "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:aot [clj.core]
:dependencies [[org.clojure/clojure "1.7.0"]])
一旦您在 jar 中看到 .class
文件,在您的 classpath 中看到该 jar,您在 Java 代码中的导入应该可以正常工作。
如文档中所述 (https://clojure.org/reference/compilation):
Clojure compiles all code you load on-the-fly into JVM bytecode, but sometimes it is advantageous to compile ahead-of-time (AOT). Some reasons to use AOT compilation are:
To deliver your application without source
To speed up application startup
To generate named classes for use by Java
To create an application that does not need runtime bytecode generation and custom classloaders
另见 http://clojure-doc.org/articles/language/interop.html:
AOT
gen-class
requires ahead-of-time (AOT) compilation. It means that before using the classes defined withgen-class
, the Clojure compiler needs to produce .class files fromgen-class
definitions.