JavaからLuaスクリプトを呼び出す、またはその逆

画像

最近、このような問題に遭遇しましたが、Luaの人気を考えると、ネットワーク上に資料がほとんどないことに非常に驚きました。 結局のところ、JavaのLuaスクリプトを操作するためのライブラリはかなりありますが、それらはすべて独自のニュアンスを持っています。 結局のところ 、Luaを書いたのと同じ開発者のLuaJavaライブラリを使用するのが最善です。



LuaJavaライブラリの構築


ソースでアーカイブを解凍し、特別なフォルダーでアセンブリを実行し、そこからアセンブルされたjarファイルをプロジェクトに接続することをお勧めします。 このフォルダーへのパスもClassPathで記述する必要があります。 jarアーカイブをビルドし、それをjavaプロジェクトのあるフォルダーにコピーすると、プログラムは起動しません。 しかし、それについては以下をご覧ください。

マニュアルページには、LinuxおよびOSXのユーザーが、簡単なmakeコマンドを使用してソースからライブラリをアセンブルし、構成ファイル(config)に小さな変更を加えることができると書かれています。 このファイルは最初は次のようになります

#############################################################

#Linux/BSD/Mac

LUA_DIR= /usr/local/share/lua/5.1.1

LUA_LIBDIR= /usr/local/lib

LUA_INCLUDES= /usr/local/include

JDK= $(JAVA_HOME)

# For Mac OS, comment the above line and uncomment this one

#JDK=/Library/Java/Home



# Full path to Lua static library

LIB_LUA=$(LUA_LIBDIR)/liblua.a



#Linux/BSD

LIB_EXT= .so

#Mac OS

#LIB_EXT= .jnilib



LIB_PREFIX= lib



#Linux/BSD

LIB_OPTION= -shared

#Mac OS

#LIB_OPTION= -dynamiclib -all_load



## On FreeBSD and Mac OS systems, the following line should be commented

DLLIB= -ldl



WARN= -O2 -Wall -fPIC -W -Waggregate-return -Wcast-align -Wmissing-prototypes -Wnested-externs -Wshadow -Wwrite-strings

INCS= -I$(JDK)/include -I$(JDK)/include/linux -I$(LUA_INCLUDES)

CFLAGS= $(WARN) $(INCS)



CC= gcc



#########################################################

VERSION= 1.1

PKG= luajava-$(VERSION)

TAR_FILE= $(PKG).tar.gz

ZIP_FILE= $(PKG).zip

JAR_FILE= $(PKG).jar

SO_FILE= $(LIB_PREFIX)$(PKG)$(LIB_EXT)

DIST_DIR= $(PKG)



# $Id: config,v 1.12 2006/12/22 14:06:40 thiago Exp $






すぐにmakeを実行しようとすると、良いことは何も起こりません。 ライブラリを正常にビルドするために必要なことは次のとおりです。

1. JAVA_HOME環境変数を作成するか、設定ファイルに登録して、javaがインストールされているフォルダーへのパスを指定します。 構成ファイルの最初の行にこの変数を追加しました:

JAVA_HOME= /usr/lib/jvm/java-6-sun-1.6.0.26







2. ここから Luaバイナリダウンロードします 。 Linuxアーカイブ### _ lib.tar.gzが必要です。 アーカイブを解凍した後、ファイルliblua5.1aおよびliblua5.1.soを/ usr / local / libフォルダーにコピーし、ファイルをincludeフォルダーから/ usr / local / includeフォルダーにコピーする必要があります。 その後、構成ファイルの行を置き換えます

LIB_LUA=$(LUA_LIBDIR)/liblua.a







LIB_LUA=$(LUA_LIBDIR)/liblua5.1.a







3. gccもインストールする必要があります。



これで、ライブラリをビルドできます。 makeコマンドを実行すると、luajava-1.1.jarとlibluajava-1.1.soの2つのファイルが表示されます。 マニュアルには、.jarをプロジェクトのlib /フォルダーに配置する必要があり、.soファイルはJRE bin /フォルダー、またはLD_LIBRARY_PATH変数が示すフォルダーのいずれかにあると書かれています。 このファイルをJRE bin /フォルダーに配置します。



Javaプロジェクトの構成


Javaプロジェクトでは、外部luajava-1.1.jarライブラリを接続する必要があります。 また、少し先を見て、VM引数に行を追加する必要があります

-Djava.library.path=[ , LuaJava]







これで、Luaスクリプトを安全に記述し、プログラムからそれらにアクセスできます。 これは、org.keplerproject.luajava.LuaStateクラスを使用して行われます。 Lua関数を呼び出すための特別なクラスが記述されている例に出会いまし 。 私が使用しているクラスの例を次に示します。



 import org.keplerproject.luajava.LuaObject; import org.keplerproject.luajava.LuaState; import org.keplerproject.luajava.LuaStateFactory; public class LuaScriptLoader { private LuaState luaState; public LuaScriptLoader(String fileFullName) { luaState = LuaStateFactory.newLuaState(); luaState.openLibs(); luaState.LdoFile(fileFullName); } public void closeScript() { luaState.close(); } /** * ,  Lua- getRoomDescription,     * * @return    */ public String getRoomDescription() { luaState.getGlobal("getRoomDescription"); luaState.call(0, 1); LuaObject lo = luaState.getLuaObject(1); luaState.pop(1); return lo.getString(); } /** * ,     Lua- * * @param functionName -   * @param adapter -  LuaAdapter,     */ public void runScriptFunction(String functionName, LuaAdapter adapter) { luaState.getGlobal(functionName); luaState.pushJavaObject(adapter); luaState.call(1, 0); } }
      
      







プログラムはプログラミング環境から起動されます。 .jarファイルをプログラムで実行する場合は、次の2つのことを行う必要があります。

1.エクスポートするときは、Class-Path属性を登録する必要があるマニフェストファイルを使用します

Class-Path: [ , LuaJava]/luajava-1.1.jar







2.環境VMの引数で指定されているのと同じキーを使用して.jarファイルを実行する必要があります

-Djava.library.path=[ , LuaJava]







LuaStateクラスの呼び出しメソッドを呼び出すと、2つの整数パラメーターが渡されます。 これは、引数の数と戻り値の数です。 getRoomDescription()メソッドは、Lua関数(0引数、1戻り値)から結果を取得する方法を示し、runScriptFunction()メソッドでは、javaオブジェクトをスクリプト(1引数、0戻り値)に渡す方法を示します。 LuaAdapterクラスは、いくつかのパブリックメソッドを持つ私のクラスです。 これらのメソッドは、スクリプトから呼び出すことができます。 スクリプトファイルの例を次に示します。



 function getRoomDescription() return "" end function processMessage(adapter) local message = adapter:getMessage() local user = adapter:getUser() local nick = user:getNick() adapter:sendMessageToRoomAndUser(user, nick..": "..message, "") end function userEnter(adapter) local user = adapter:getUser() local nick = user:getNick() adapter:sendMessageToRoomAndUser(user, "  "..nick, "   ") end function userLeft(adapter) local nick = adapter:getUser():getNick() adapter:sendMessageToRoom(" "..nick.."   ") end
      
      







この例では、Luaを使用して、ユーザーがチャットできる会議室がスクリプト化されています。 LuaAdapterクラスにあるすべてのパブリックメソッドが正常に呼び出され、実行されます。



UPD:もう一つ忘れました。 上記で説明したように(Lua関数へのパラメーターとしてオブジェクトを渡す)だけでなく、LuaのJavaクラスとオブジェクトを操作できます。 LuaJava マニュアルには、さらにいくつかの方法が記載されています。 私は最初の2つで作業しましたが、問題なく動作し、残りは不必要に試行しませんでした。 最初の2つの方法を説明します。

1. LuaJavaライブラリのnewInstance(className、...)関数を呼び出します。 関数の最初のパラメーターはjavaクラスの完全な名前で、残りはコンストラクターパラメーターです。 この関数を呼び出した結果は、作業できる新しいJavaオブジェクトになります。

例:



 obj = luajava.newInstance("java.lang.Object")
      
      







パラメーターとして名前を渡すことでクラスを呼び出すこともできます(たとえば、「myproject.mypackage.MyClass」)。 しかし、ここで私が会ったことのないニュアンスがあるかもしれません:





2. LuaJavaライブラリのbindClass(className)関数を呼び出します。 この関数は、名前が指定されたjavaクラスの静的フィールドとメソッドにアクセスできるオブジェクトを返します。

例:



 sys = luajava.bindClass("java.lang.System") print ( sys:currentTimeMillis() )
      
      







クラスを(同じニュアンスで)呼び出すこともできます。

これらのLua関数は1つのプロジェクトからのみ呼び出しました。関数では、このプロジェクトのクラスにのみアクセスしたため、問題は発生しませんでした



UPDニュアンスがありました。 呼び出しメソッドは、スクリプトに存在する可能性のあるエラーをキャッチできません。 スクリプトにエラーがある場合、プログラム全体がクラッシュします。 Iksepshenovはこの方法を放棄しません。 Googleが解決した唯一の解決策は、別のスレッドからスクリプト呼び出しを実行することでした。 しかし、これは非常にいです。 しかし、LuaStateクラスにはpcallメソッドがあります。



 public int pcall(int nArgs, int nResults, int errFunc)
      
      







呼び出しが成功した場合は値0を返し、失敗した呼び出しの結果としてゼロ以外の値を返します。 最初の2つの引数は呼び出しメソッドの引数を繰り返します。最後のパラメーターは、おそらくエラー処理関数を指している必要があります。 この場合、エラーの説明はLuaStateオブジェクトに保存され、スクリプト関数が呼び出されます。 これで、私のrunScriptFunctionメソッドは次のようになります。



  public void runScriptFunction(String functionName, LuaAdapter adapter) { luaState.getGlobal(functionName); luaState.pushJavaObject(adapter); int res = luaState.pcall(1, 0, 0); if(res != 0) { Main.log(Level.SEVERE, "LuaScriptLoader call error: " + luaState.toString(-1)); } } }
      
      






All Articles