uehaj's blog

Grな日々 - GroovyとかGrailsとかElmとかRustとかHaskellとかReactとかFregeとかJavaとか -

Groovy+JNA

JNA(Java Native Access)というものがあります(https://jna.dev.java.net/)。これはJavaから動的にDLL中の関数を呼び出すものです。「動的に」ということの意味は、しち面倒くさくバグも作り出しやすい、悪名高きJNI(Java Native Interface)を使わずに、そもそもCコンパイラなどを一切使わずに、DLL(Unix環境ではso)に含まれる関数を呼び出すことができるということです。jnaの配布物(jna.jar)にはさまざまなOS用のディスパッチャが含まれているので、プラットフォーム独立かのように錯覚するぐらいです*1

ということで、動的つながり(強引)ということで、Groovyから呼んで見ます。

jna.jarをCLASSPATHに通せば*2たとえば、Pure Javaだけではできない「カレントディレクトリを移動する」という操作を

@Grab('net.java.dev.jna:jna:3.2.2')
import com.sun.jna.*;
import com.sun.jna.win32.*;

interface CLibrary extends Library {
  CLibrary INSTANCE = Native.loadLibrary("msvcrt", CLibrary.class);
   int _chdir(String dir);
}

CLibrary.INSTANCE._chdir(args[0])
println "pwd".execute().text

はいこのとおり。これはWindowsの場合であり、_chdir関数はmsvcrt.dllから読み込みます。
Windowsの場合、Win32APIを直たたきで

@Grab('net.java.dev.jna:jna:3.2.2')
import com.sun.jna.*;
import com.sun.jna.win32.*;

interface Kernel32Library extends StdCallLibrary {
  Kernel32Library INSTANCE = Native.loadLibrary("kernel32", Kernel32Library.class);
  boolean SetCurrentDirectoryA(String dir);
}

Kernel32Library.INSTANCE.SetCurrentDirectoryA(args[0])
println "pwd".execute().text

でもオーケーです。
MacOS X(あるいはUnix系OS)なら

@Grab('net.java.dev.jna:jna:3.2.2')

import com.sun.jna.*;
import com.sun.jna.win32.*;

interface CLibrary extends Library {
  CLibrary INSTANCE = Native.loadLibrary("c", CLibrary.class);
   int chdir(String dir);
}

CLibrary.INSTANCE.chdir(args[0])
println "pwd".execute().text

のようになります。

Cで通常呼び出す関数名(chdir,SetCurrentDirectory)と、実際にdllに含まれているDLLのエントリファンクション名(_chdir, SetCurrentDirectoryA)が異なっているときがあるというのは要注意。C言語からはマクロとかで変換されています。

上では、インターフェース定義を経由していますが、「GroovyならMOPがあるからいらないんじゃないかな?」とだめ元で直に呼んでやってみたらダメでした。たぶんJNAでは対象メソッドの呼び出しに動的Proxyを使ってると思うので、原理的に駄目でしょう。GroovyならMOPを使って解析して呼ぶこともできるようにすることもできるかもしれません。

*1:もちろん、プラットフォームごとに関数自体の有無がことなり仕様もことなるのでプラットフォーム依存であることには変わりません。でもたとえば、C標準関数の範囲なら有る程度はいけるかも

*2:以下ではGrabしてるのでダウンロード/インストールも不要です。

擬人化キャラクター

id:bikisukeさんの知人の方がGroovyの擬人化キャラクター「Groovyたん」を描いてくれました。
気さくな感じで良い方ですね!イカす!

http://d.hatena.ne.jp/bikisuke/20091214/1260812173

JGGUGの平均年齢が若が返った気がする!(ただし気分的に)
この記事ジェシカ=グルービーたんとも仲良しになるといいね。

友達の「アラフォーたん」も期待!

(追記)作者のid:trazukaさんもエントリを書かれています。
http://d.hatena.ne.jp/torazuka/20091216/p1
素敵なGroovyたんをありがとうございます!
f:id:uehaj:20091217100718j:image
耳のイアリングは、Groovyロゴのでしょうか。
良く見ると色調もGroovyロゴのイメージにぴったり。