重慶分公司,新征程啟航
為企業(yè)提供網(wǎng)站建設(shè)、域名注冊(cè)、服務(wù)器等服務(wù)
為企業(yè)提供網(wǎng)站建設(shè)、域名注冊(cè)、服務(wù)器等服務(wù)
如何在Java中使用Lua腳本語言是本文要介紹的內(nèi)容,主要是來學(xué)習(xí)LUA腳本語言在JAVA中如何來使用,Lua就不說了, 現(xiàn)在比較熱門, 語法也很簡單. 為了在Java中調(diào)用, 折騰了比較長的時(shí)間, 就把一些東西記在下面.來看詳細(xì)內(nèi)容講解。
在做網(wǎng)站、網(wǎng)站制作中從網(wǎng)站色彩、結(jié)構(gòu)布局、欄目設(shè)置、關(guān)鍵詞群組等細(xì)微處著手,突出企業(yè)的產(chǎn)品/服務(wù)/品牌,幫助企業(yè)鎖定精準(zhǔn)用戶,提高在線咨詢和轉(zhuǎn)化,使成都網(wǎng)站營銷成為有效果、有回報(bào)的無錫營銷推廣。創(chuàng)新互聯(lián)專業(yè)成都網(wǎng)站建設(shè)10余年了,客戶滿意度97.8%,歡迎成都創(chuàng)新互聯(lián)客戶聯(lián)系。
Lua是支持內(nèi)嵌在C程序中的, 但是官方不支持Java. 在網(wǎng)上查了下, 有LuaJava開源庫, 拿來試用了一下, 發(fā)現(xiàn)這個(gè)庫還算比較完善的.
這個(gè)LuaJava實(shí)際上就是按照Lua官方文檔, 把Lua的C接口通過JNI包裝成Java的庫. 下載, 里面是一個(gè).dll, 一個(gè).jar. 把.dll放到j(luò)ava.library.path下, 再把.lib放到classpath中, helloworld運(yùn)行OK.
但是, 測(cè)試的時(shí)候, 很快發(fā)現(xiàn)了第一個(gè)問題: 在調(diào)用LuaJava中提供的LuaState.pushInteger 方法的時(shí)候, 出現(xiàn)了錯(cuò)誤 : Unsatisfied Link Error. 其他的LuaState.pushNumber方法倒是沒有問題. 用Depends工具看了下, 這個(gè).dll居然沒有導(dǎo)出pushInteger這個(gè)函數(shù). 暈....
下載LuaJava的源代碼, 查看了下Luajava.c 和 Luajava.h, 發(fā)現(xiàn)果然里面有點(diǎn)問題, 在.h里面定義了JNI中對(duì)應(yīng)Java函數(shù)的C函數(shù)
JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushInteger
但是.c中沒有實(shí)現(xiàn)這個(gè)函數(shù). 無語, 看來大馬虎哪都有啊. 幸虧有源代碼, 照貓畫虎在Luajava.c中加上這個(gè)函數(shù)的實(shí)現(xiàn),
JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushInteger (JNIEnv * env, jobject jobj, jobject cptr, jint i) { lua_State * L = getStateFromCPtr( env , cptr ); lua_pushinteger(L, i); }
然后編譯. 編譯也出現(xiàn)了問題了, 官方文檔中說可以用VC++來Build, 但是沒有說官方用的是什么版本. 我用VC2005就不行. 好在Luajava比較小, 就一個(gè).h 一個(gè) .c , 在VC中新建一個(gè).dll項(xiàng)目, 把文件加進(jìn)去, 修改一下build參數(shù) (Include 需要加上lua的頭文件, lib中需要加上lua的.lib文件, 另外要選上 Compile as C Code (/TC) ) Build, 通過了.
這時(shí)再在Java中調(diào)用pushInteger方法就沒有問題了.
在測(cè)試中, 發(fā)現(xiàn)Luajava提供的文檔中, 對(duì)于Lua腳本怎么調(diào)用Java對(duì)象/方法很詳細(xì), 但是在Java中怎么調(diào)用Lua函數(shù)/取得返回值 就沒有. 參考了 的Lua C文檔, 實(shí)現(xiàn)了傳遞對(duì)象到Lua中并取得返回值的代碼:
Test1: 測(cè)試傳遞簡單類型, 并取得返回值:
Lua 腳本(test.lua):
function test(a,b) return a+b end
Java代碼:
static { //加載Lua5.1.dll, 因?yàn)長uaJava最后還是要調(diào)用Lua的東西 System.loadLibrary("lua5.1"); } public static void main(String[] argu) throws LuaException { LuaState L = LuaStateFactory.newLuaState(); L.openLibs(); //讀入Lua腳本 int error = L.LdoFile("test.lua"); if (error != 0) { System.out.println("Read/Parse lua file error. Exit."); return; } //找到函數(shù)test L.getField(LuaState.LUA_GLOBALSINDEX, "test"); //參數(shù)1壓棧 L.pushInteger(1); //參數(shù)2壓棧 L.pushInteger(2); //調(diào)用!! 一共兩個(gè)參數(shù), 1個(gè)返回值 L.call(2, 1); //保存返回值, 到a中 L.setField(LuaState.LUA_GLOBALSINDEX, "a"); //讀入a LuaObject l = L.getLuaObject("a"); //打印結(jié)果. System.out.println("Result is " + l.getString()); L.close(); }
測(cè)試2: 傳遞Java對(duì)象
class Value { public int i; public void inc() { i++; } public int get() { return i; } public String toString() { return "Value is " + i; } }
Lua腳本: (該腳本中調(diào)用兩次對(duì)象的inc方法, 并調(diào)用get方法輸出結(jié)果)
function test1(v) v:inc(); v:inc(); print("In lua: " .. v:get()); return v end
Java 代碼: (前面都一樣, 略)
//找到函數(shù)test1 L.getField(LuaState.LUA_GLOBALSINDEX, "test1"); //生成新的對(duì)象供測(cè)試 Value v = new Value(); //對(duì)象壓棧 L.pushObjectValue(v); //調(diào)用函數(shù)test1, 此時(shí)1個(gè)參數(shù), 1個(gè)返回值 L.call(1, 1); //結(jié)果放在b中. L.setField(LuaState.LUA_GLOBALSINDEX, "b"); LuaObject l = L.getLuaObject("b"); System.out.println("Result is " + l.getObject());
運(yùn)行結(jié)果:
Result is Value is 2 In lua: 2
和預(yù)期的一致.
實(shí)現(xiàn)一個(gè)怪物的創(chuàng)建,把lua里的設(shè)定當(dāng)作初始狀態(tài)傳給monstor,名字為sample monstor,防御10,攻擊10,生命100
1.先導(dǎo)入lib--luajava-1.1.jar
import org.keplerproject.luajava.LuaState; import org.keplerproject.luajava.LuaStateFactory; public class Load{ LuaState luaState; /** * Constructor * @param fileName File name with Lua . */ Load(final String fileName) { this.luaState = LuaStateFactory.newLuaState(); this.luaState.openLibs(); this.luaState.LdoFile(fileName); } /** * Ends the use of Lua environment. */ void close() { this.luaState.close(); } /** * Call a Lua inside the Lua to insert * data into a Java object passed as parameter * @param Name Name of Lua . * @param obj A Java object. */ void run(String Name, Object obj) { this.luaState.getGlobal(Name); this.luaState.pushJavaObject(obj); this.luaState.call(1,0); } } public class Monster{ /* Info */ protected String race; protected int defense; protected int attack; protected int life; /* */ private Load ; public Monster(String race) { /* Loads Lua for this race.*/ this. = new Load(race+".lua"); /*Call Lua create .*/ .run("create", this); } public void setRace(String race) { this.race = race; } public String getRace() { return race; } public int getDefense() { return this.defense; } public void setDefense(int defense) { this.defense = defense; } public int getLife() { return this.life; } public void setLife(int life) { this.life = life; } public void setAttack(int attack) { this.attack = attack; } public int getAttack() { return this.attack; } } monstor.lua--- create(monster) monster:setRace("Sample Monster") monster:setDefense(10) monster:setAttack(10) monster:setLife(100) end
但總是拋出這個(gè)錯(cuò)誤:
PANIC: unprotected error in call to Lua API (Invalid method call. No such method.)
不知為何,以后用到的時(shí)候再research.
已經(jīng)查出來,原來在Monster類中少了個(gè)方法:
public void setRace(String race) { this.race = race; }
怪不得會(huì)找不到,
要在一lua文件a.lua里導(dǎo)入其他的lua文件b.lua,用require "b"
如果要從lua中運(yùn)算后得到返回參數(shù),則需要做一下修改:在lua文件中改成:
create(monster) monster:setRace("Sample Monster") monster:setDefense(10) monster:setAttack(10) monster:setLife(100) return monster end
在Load.java中的run改成如下:
void run(String Name, Object obj) { this.luaState.getGlobal(Name); this.luaState.pushJavaObject(obj); this.luaState.call(1, 1);// 一個(gè)參數(shù),0個(gè)返回 try { Object object =luaState.getObjectFromUserdata(1); } catch (LuaException e) { e.printStackTrace(); } }
轉(zhuǎn)載僅供參考,版權(quán)屬于原作者。祝你愉快,滿意請(qǐng)采納哦
如果shell腳本和java程序運(yùn)行在不同的服務(wù)器上,可以使用遠(yuǎn)程執(zhí)行Linux命令執(zhí)行包,使用ssh2協(xié)議連接遠(yuǎn)程服務(wù)器,并發(fā)送執(zhí)行命令就行了,ganymed.ssh2相關(guān)mave配置如下,你可以自己百度搜索相關(guān)資料。
如果shell腳本和java程序在同一臺(tái)服務(wù)器上,
這里不得不提到j(luò)ava的process類了。
process這個(gè)類是一個(gè)抽象類,封裝了一個(gè)進(jìn)程(你在調(diào)用linux的命令或者shell腳本就是為了執(zhí)行一個(gè)在linux下執(zhí)行的程序,所以應(yīng)該使用process類)。
process類提供了執(zhí)行從進(jìn)程輸入,執(zhí)行輸出到進(jìn)程,等待進(jìn)程完成,檢查進(jìn)程的推出狀態(tài),以及shut down掉進(jìn)程。
dependency??
groupIdcom.ganymed.ssh2/groupId??
artifactIdganymed-ssh2-build/artifactId??
version210/version??
/dependency
本地執(zhí)行命令代碼如下:
String?shpath="/test/test.sh";???//程序路徑
Process?process?=null;
String?command1?=?“chmod?777?”?+?shpath;
process?=?Runtime.getRuntime().exec(command1);
process.waitFor();
過CommandHelper.execute方法可以執(zhí)行命令,該類實(shí)現(xiàn)
復(fù)制代碼代碼如下:
package javaapplication3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
*
* @author chenshu
*/
public class CommandHelper {
//default time out, in millseconds
public static int DEFAULT_TIMEOUT;
public static final int DEFAULT_INTERVAL = 1000;
public static long START;
public static CommandResult exec(String command) throws IOException, InterruptedException {
Process process = Runtime.getRuntime().exec(command);
CommandResult commandResult = wait(process);
if (process != null) {
process.destroy();
}
return commandResult;
}
private static boolean isOverTime() {
return System.currentTimeMillis() - START = DEFAULT_TIMEOUT;
}
private static CommandResult wait(Process process) throws InterruptedException, IOException {
BufferedReader errorStreamReader = null;
BufferedReader inputStreamReader = null;
try {
errorStreamReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
inputStreamReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
//timeout control
START = System.currentTimeMillis();
boolean isFinished = false;
for (;;) {
if (isOverTime()) {
CommandResult result = new CommandResult();
result.setExitValue(CommandResult.EXIT_VALUE_TIMEOUT);
result.setOutput("Command process timeout");
return result;
}
if (isFinished) {
CommandResult result = new CommandResult();
result.setExitValue(process.waitFor());
//parse error info
if (errorStreamReader.ready()) {
StringBuilder buffer = new StringBuilder();
String line;
while ((line = errorStreamReader.readLine()) != null) {
buffer.append(line);
}
result.setError(buffer.toString());
}
//parse info
if (inputStreamReader.ready()) {
StringBuilder buffer = new StringBuilder();
String line;
while ((line = inputStreamReader.readLine()) != null) {
buffer.append(line);
}
result.setOutput(buffer.toString());
}
return result;
}
try {
isFinished = true;
process.exitValue();
} catch (IllegalThreadStateException e) {
// process hasn't finished yet
isFinished = false;
Thread.sleep(DEFAULT_INTERVAL);
}
}
} finally {
if (errorStreamReader != null) {
try {
errorStreamReader.close();
} catch (IOException e) {
}
}
if (inputStreamReader != null) {
try {
inputStreamReader.close();
} catch (IOException e) {
}
}
}
}
}
CommandHelper類使用了CommandResult對(duì)象輸出結(jié)果錯(cuò)誤信息。該類實(shí)現(xiàn)
復(fù)制代碼代碼如下:
package javaapplication3;
/**
*
* @author chenshu
*/
public class CommandResult {
public static final int EXIT_VALUE_TIMEOUT=-1;
private String output;
void setOutput(String error) {
output=error;
}
String getOutput(){
return output;
}
int exitValue;
void setExitValue(int value) {
exitValue=value;
}
int getExitValue(){
return exitValue;
}
private String error;
/**
* @return the error
*/
public String getError() {
return error;
}
/**
* @param error the error to set
*/
public void setError(String error) {
this.error = error;
}
}
腳本對(duì)于大多數(shù)程序員來說應(yīng)該不陌生了吧。
今天我們就一起來了解一下,在使用java編程開發(fā)語言編寫API腳本的時(shí)候都需要注意哪些問題。
Java腳本化API為誰準(zhǔn)備?腳本語言的一些有用的特性是:方便:大多數(shù)腳本語言都是動(dòng)態(tài)類型的。
您通常可以創(chuàng)建新的變量,而不聲明變量類型,并且您可以重用變量來存儲(chǔ)不同類型的對(duì)象。
此外,腳本語言往往會(huì)自動(dòng)執(zhí)行許多類型的轉(zhuǎn)換,例如,必要時(shí)將數(shù)字10轉(zhuǎn)換為“10”。
開發(fā)快速原型:您可以避免編輯編譯運(yùn)行周期,只使用“編輯運(yùn)行”!應(yīng)用擴(kuò)展/定制:你可以“具體化”的部分應(yīng)用程序,例如一些配置腳本,業(yè)務(wù)邏輯/規(guī)則和財(cái)務(wù)應(yīng)用中的數(shù)學(xué)表達(dá)式。
為應(yīng)用添加命令行模式,用于調(diào)試、運(yùn)行時(shí)配置/部署時(shí)間。
現(xiàn)在大多數(shù)應(yīng)用程序都有一個(gè)基于Web的GUI配置工具。
但是系統(tǒng)管理員/部署人員常常喜歡命令行工具。
一個(gè)“標(biāo)準(zhǔn)”的腳本語言可以用來實(shí)現(xiàn)這個(gè)目的,而不是發(fā)明特設(shè)的腳本語言。
Java腳本API是一種獨(dú)立于框架的腳本語言,使用來自于Java代碼的腳本引擎。
通過java腳本API,可以使用Java語言編寫定制/可擴(kuò)展的應(yīng)用程序并將自定義腳本語言選擇留給終用戶。
Java應(yīng)用程序開發(fā)者不需要在開發(fā)過程中選擇擴(kuò)展語言。
如果你使用JSR-223API來編寫應(yīng)用,那么你的用戶可以使用任何JSR-223兼容的腳本語言。
腳本包Java腳本功能是在javax.script包中。
這是一個(gè)比較小的,簡單的API。
腳本的出發(fā)點(diǎn)是ScriptEngineManager類。
一個(gè)ScriptEngineManager對(duì)象可以通過jar文件的服務(wù)發(fā)現(xiàn)機(jī)制發(fā)現(xiàn)腳本引擎。
它也可以實(shí)例化腳本引擎來解釋使用特定的腳本語言編寫的腳本。
腳本變量當(dāng)你的java應(yīng)用程序嵌入腳本引擎和腳本,你可能希望將您的應(yīng)用程序?qū)ο鬄槿肿兞勘┞队谀_本中。
這個(gè)例子演示了如何將您的應(yīng)用程序?qū)ο笞鳛槿肿兞勘┞队谀_本中。
我們?cè)趹?yīng)用程序中創(chuàng)建一個(gè)java.io.File對(duì)象作為全局變量,名稱是file。
江蘇電腦培訓(xùn)發(fā)現(xiàn)該腳本可以訪問變量,例如,它可以調(diào)用它的公共方法。
注意訪問java對(duì)象、領(lǐng)域和方法的語法依賴于腳本語言。
JavaScript支持“自然”的類似java的語法。
如果是jython,也就是運(yùn)行在Jvm上的python的話,可以使用JSR223,JDK1.6已經(jīng)包含了該擴(kuò)展包。JSR223是一個(gè)用于解析多種腳本語言的庫包,其中包括Jython。除了JSR223包之外,還需要jython-engine.jar包。
ScriptEngine engine = new ScriptEngineManager().getEngineByName("python");
try
{
engine.eval(new FileReader("./script/listing.py"));
}
catch(ScriptException se)
{
}
catch(IOException ie)
{
}
或者參考:
很久之前用過ScriptEngine,對(duì)在Jvm上的腳本語言比如jruby,jython,groovy等支持性都很好,有點(diǎn)忘記了。