#:g1: LispWorks 7購入への道(3) ─ Java連携を試す

Posted 2015-07-20 13:50:09 GMT

 Allegro CLでは、結構前からjLinkerという機能がありCommon LispとJavaが連携できたりしましたが、LispWorksは最新の7から連携機能が付いたようです。

普段Javaを呼んだりすることはあまりありませんが、折角なのでどんなものか試してみることにしました。

下準備

LispWorks Java interfaceを利用するには、Linuxの場合、libjvm.soが利用できるようになっている必要があるようです。
LD_LIBRARY_PATHで設定するか、ldconfigで設定することになるかと思います。
64bit Debian GNU/Linuxでは、下記のパスを登録すればよいようでした。

/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server/

LispWorksへパッチの適用

 このJava連携機能ですが、ファイルの同梱漏れがあったようで、lispcalls.jarをサイトからダウンロードして適切な場所に設置する必があります。

(2015-07-20日現在、最新のインストーラからインストールを実行してもlispcalls.jarは導入されません。)

Javaを呼んでみる

 利用にはモジュールをロードして初期化という流れのようです。 下記は、joda-timeとicuを呼んでみている例と、入門サイトのちょっとした例を書き換えてみた例です。

(require "java-interface")

(lw-ji:init-java-interface :jvm-library-path T :java-class-path '("/var/tmp/joda-time-2.8.1/joda-time-2.8.1.jar" "/usr/share/java/com.ibm.icu-4.2.1.1.jar"))

(lw-ji:import-java-class-definitions "org.joda.time.DateTime") (lw-ji:import-java-class-definitions "com.ibm.icu.text.Normalizer")

(let ((date (|org.joda.time|:datetime.new))) (list (|org.joda.time|:datetime.getyear date) (|org.joda.time|:datetime.getmonthofyear date) (|org.joda.time|:datetime.getdayofmonth date) (|org.joda.time|:datetime.gethourofday date) (|org.joda.time|:datetime.getminuteofhour date) (|org.joda.time|:datetime.getsecondofminute date))) ;=> (2015 7 20 22 11 23)

(defun normalize-string (s) (|com.ibm.icu.text|:normalizer.normalize s (lw-ji:read-java-field "com.ibm.icu.text.Normalizer.NFKC")))

(normalize-string "ABCDEFG12345アイウエオABCDEFG12345アイウエオ") ;=> "ABCDEFG12345アイウエオABCDEFG12345アイウエオ"

なお、lw-ji:write-java-class-definitions-to-fileを使うとJavaのクラス定義が書き出せて、後でこのファイルをロードすることで lw-ji:import-java-class-definitionsの手間を省くことも可能なようです。

(lw-ji:write-java-class-definitions-to-file "org.joda.time.DateTime" "/tmp/joda-datetime.lisp")
(lw-ji:write-java-class-definitions-to-file "com.ibm.icu.text.Normalizer" "/tmp/icu.lisp")

(load (compile-file "/tmp/icu.lisp)") ...

JavaDrive: テキストをファイルに書き込む の例をlw-jiで

(macrolet ((jimport (&rest classes)
             `(progn
                ,@(mapcar (lambda (c)
                            `(lw-ji:import-java-class-definitions ,c))
                          classes))))
  (jimport "java.io.File"
           "java.io.FileWriter"
           "java.io.BufferedWriter"
           "java.io.PrintWriter"
           "java.io.IOException"))

(defun check-before-wite-file (file) (and (|java.io|:file.exists file) (|java.io|:file.canwrite file)))

(let* ((filename "/tmp/text.txt") (file (|java.io|:file.new filename))) (if (check-before-wite-file file) (let ((pw (|java.io|:printwriter.new (|java.io|:bufferedwriter.new (|java.io|:filewriter.new file))))) (unwind-protect (flet ((output (msg) (|java.io|:printwriter.println pw msg))) (output "今日の最高気温は") (output 10) (output "度です")) (|java.io|:printwriter.close pw))) (error "ファイルに書き込めません")) (hcl:file-string filename :external-format :utf-8)) ;=> "今日の最高気温は ; 10 ; 度です ; "

まとめ

Javaが呼べるCommon Lisp処理系というと、Allegro CLのjLinkerの他にJVMを利用した処理系であるABCLがあります。
API的には、jLinkerとABCLは似ている所がありますが、LispWorks Java Interfaceは、これらとはちょっと違った雰囲気になっているようです。


HTML generated by 3bmd in LispWorks 7.0.0

comments powered by Disqus