简体   繁体   English

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

[英]How can I export a Java class (.jar) from Clojure?

I am relatively novice at Clojure and Java. 我是Clojure和Java的新手。 I have an existing Clojure project someone else wrote that I am trying to embed in NodeJS using node-java . 我有一个现有的Clojure项目,其他人写道我试图使用node-java嵌入NodeJS。

Clojure Clojure的

The project defines a namespace that provides certain public functions, like so: 该项目定义了一个提供某些公共函数的命名空间,如下所示:

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

(defn dosomething ...)
(defn dosomethingelse ...)

I have built the project with leiningen ( lein jar and lein uberjar ). 我用leiningen( lein jarlein uberjar )建造了这个项目。

Questions 问题

The #import() docs on node-java say I need to import a java class like so: node-java上的#import()文档说我需要像这样导入一个java类:

const java = require('java');
var Test = java.import('Test');
  1. How can I access these functions (presumably as Java class static methods?) 我如何访问这些函数(可能是Java类静态方法?)
  2. Am I approaching this all wrong? 我接近这一切都错了吗? =) =)

Update 更新

Thanks to Magos (answer below) I made a little more progress. 感谢Magos(以下回答),我取得了一些进展。 It turns out I can use (:gen-class :name my.name) in the (ns ...) scope to tell it to generate a class. 事实证明,我可以在(ns ...)范围内使用(:gen-class :name my.name)来告诉它生成一个类。 If I add a profile to the project.clj like so: 如果我向project.clj添加一个配置文件,如下所示:

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

It will compile and I can now see the class in Node. 它将编译,我现在可以看到Node中的类。 I still haven't figured out how to export the methods, though. 不过,我仍然没有想出如何导出这些方法。 Working on that part now. 现在正在努力工作。

Since someone else wrote the Clojure, I'll assume you aren't in control of it. 由于其他人写了Clojure,我会假设你无法控制它。 The recommended approach for using Clojure code from another JVM language is bootstrapping from the class clojure.java.api.Clojure . 从另一种JVM语言使用Clojure代码的推荐方法是从类clojure.java.api.Clojure引导。 This class allows you to resolve Vars from Clojure, and by resolving and invoking the other core Clojure functions you can load your own code. 此类允许您从Clojure解析Vars,通过解析和调用其他核心Clojure函数,您可以加载自己的代码。 Based on your example it might look something like this: 根据您的示例,它可能看起来像这样:

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(....

If you do control the Clojure, :gen-class allows you to export functions as methods of the namespace's generated class . 如果你确实控制了Clojure,那么:gen-class允许你将函数导出为命名空间生成的类的方法

Note: I arrived at this through a combination of Magos's answer and clartaq's comment to the question. 注意:我通过结合Magos的回答和clartaq对该问题的评论来达到这个目的。

Here are simple instructions for how to do it. 以下是如何操作的简单说明。 Let's assume you have this (simple) clojure code: 假设你有这个(简单的)clojure代码:

(ns my.namespace
  "a trivial library"
  (:require [something.else :as other]))

(defn excite
  "make things more exciting"
  [mystr]
  (print-str mystr "!"))

Use these steps to expose the excite method. 使用这些步骤来公开excite方法。

  1. Create an exposed version of the method with the same signature by prefixing it with - . 使用相同的签名创建方法的公开版本,方法是在其前面加上- It should simply call the function you wish to expose. 它应该只是调用你想要公开的函数。

     (defn -excite [mystr] (excite mystr)) 
  2. Declare in (ns ...) that you want to generate a class and export methods. (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] ])) 

    Note that you may optionally remove the #^{:static true} if you do not wish to provide this as a static method. 请注意,如果您不希望将此作为静态方法提供,则可以选择删除#^{:static true}

  3. In your project.clj (assuming you are using leiningen), add ahead-of-time compilation instructions to your :profiles entry: 在您的project.clj中(假设您正在使用leiningen),将以前的编译说明添加到您的:profiles条目:

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

     lein uberjar 

The resulting .jar file will have a class my.classname with a static method excite . 生成的.jar文件将有一个类my.classname其中包含静态方法excite

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM