适用于RPG Maker VX Ace的LuaJIT 2.1.x支持。
- 准备一个32位的LuaJIT运行时DLL文件放置在项目目录中,路径为
<项目根目录>/System/lua51.dll。
- 推荐自行编译DLL以保证文件安全性
- 注意,默认要求放置位置的文件名是
lua51.dll,不是lua5.1.dll;编译或下载DLL后,可能需要重命名文件,或修改代码中的DLL文件路径配置 - 无法使用64位的LuaJIT运行时DLL
- 在Script Editor中,新建一栏,并将
lua-rmva.rb的内容粘贴进去。 - 在Event Editor中,使用
lua = Lua.new创建实例,即可使用lua.eval(code, *args)等函数运行Lua代码。
在Event Editor中:
begin
## 创建Lua实例
$lua = Lua.new if $lua == nil
lua = $lua
p "Lua: #{lua}"
## 从Lua传递数据到Ruby
p lua.eval("return 'Hello World!', 123, 4.56, true, nil")
p lua.eval("return {'A', 'B', 'C'}, function() return 'DEF' end")
## 从Ruby传递数据到Lua再返回
p lua.eval("return ...", "Hello World!", 123, 4.56, true, nil)
p lua.eval("local num1,num2,str = ...; return num1==2, num2==3.14,
str=='Hello'", 2, 3.14, 'Hello')
## 获得LuaJIT的版本信息
p lua.eval("if type(jit) == 'table' then return jit.version end")
## 故意在Lua中引发错误,由Ruby接收
# p lua.eval("error('This is an error'))",
rescue
p($!.message, $!.backtrace)
end| Ruby | Lua |
|---|---|
nil |
nil |
true, false |
true, false |
Integer, Float |
number |
String |
string |
Array, Hash |
table(+metatable) |
Method, Proc |
table(+metatable) |
Lua_WrappedObject |
原本的table,function,userdata或lightuserdata |
Object |
table(+metatable) |
| Lua | Ruby |
|---|---|
nil |
nil |
true, false |
true, false |
number |
Float |
string |
String |
table |
Lua_WrappedObject |
function |
Lua_WrappedObject |
userdata, lightuserdata |
Lua_WrappedObject |
引用Ruby对象的 table(+metatable) |
原本的Array, Hash, Method, Proc或Object |
- 在Lua中,数字只有一种数据类型
number;转换到Ruby时,所有的number都转换为Float类型成为浮点数小数,即使内容可能原本是整数 - Lua的
table,function,userdata类型来到Ruby后,按引用传递,变成Lua_WrappedObject类型指向Ruby中原对象;其上的方法具体见下面API - Ruby的
Array,Hash,Method,Proc,Object类型来到Lua后,按引用传递,变成table(+metatable)形式指向Ruby中原对象;可以在其上调用方法,具体见下面API - 跨语言按引用传递对象后,对象的引用会被一直保留(以防止在用到之前就被原语言环境回收),所以在用完这些引用后建议调用Ruby中的
Lua#release或Lua中的rgss.release取消引用,以重新允许垃圾回收机制回收这些对象 - 原本来自Lua的对象来到Ruby后返回Lua,或者原本来自Ruby的对象来到Lua后返回Ruby,都能正确保持引用,可以用Lua中的
==或Ruby中的equals?判断相等
Lua#initialize(dll_path='System/lua51.dll'):创建并初始化Lua虚拟机Lua#eval_file(filename, *args):执行一个Lua文件,args传递给文件的...变量,返回一个包含有各返回值的ArrayLua#eval(code, *args):执行一段Lua代码,args传递给代码块的...变量,返回一个包含有各返回值的ArrayLua#eval_with_buffer(code, rets_buffer, *args):执行一段Lua代码,args传递给代码块的...变量,返回值使用rets_buffer接收,避免每次调用Lua的时候都重复为返回值创建Array,从而改善性能;rets_buffer的大小表示接受返回值的个数,个数超出容量时丢弃溢出部分,个数不足容量时用nil补足Lua#close,Lua#dispose:结束使用并销毁Lua虚拟机,清除并失去所有状态,例如在关闭游戏时可以使用Lua#release(obj):取消跨语言对象的引用;重新允许垃圾回收机制回收这个对象- 和Lua中
rgss.release(x)同义,两侧中只要有一侧调用了即可生效
- 和Lua中
Lua_WrappedObject#inspect:显示关于对应Lua对象的粗略信息(只用于Debug)Lua_WrappedObject#[](x):将对象视为table,访问其元素Lua_WrappedObject#[]=(x, val):将对象视为table,设置键所对应的值Lua_WrappedObject#to_s:将对象转换为字符串,使用Lua中的tostringLua_WrappedObject#call(*args):将对象视为callable table / callable userdata / function,调用之;形式与Lua#eval(code, *args)相仿Lua_WrappedObject#call_with_buffer(rets_buffer, *args):将对象视为callable table / callable userdata / function,调用之;使用现有Array存储返回值;形式与Lua#eval_with_buffer(code, rets_buffer, *args)相仿
rgss.eval(code):执行一段Ruby代码,无参数,取得返回值rgss.call(ruby_obj, signal_name, ...):对来自Ruby的对象使用,调用其方法,并取得返回值- 也可以直接用
ruby_obj(signal_name, ...)
- 也可以直接用
rgss.release(x):取消跨语言对象的引用;重新允许垃圾回收机制回收这个对象- 和Ruby中
Lua#release(obj)同义,两侧中只要有一侧调用了即可生效
- 和Ruby中
rgss.is_ruby_object(x):判断对象是否是Ruby对象
- 任何对象
__eq:使用方式如ruby_obj1 == ruby_obj2,检查引用到的Ruby对象是否一致__tostring:使用方式如tostring(ruby_obj),显示关于对应Ruby对象的粗略信息(只用于Debug)__call:使用方式如ruby_obj(signal_name, ...),调用Ruby对象的方法,并取得返回值
下方的方法实际上都与
ruby_obj(signal_name, ...)等效,会调用Ruby中实际存在的方法;如果没能在API中找到自己需要的方法,可以直接使用ruby_obj(signal_name, ...)调用任意方法
Arrayruby_array:length(),ruby_array:size():取得元素数(Ruby中的length,size)ruby_array:get(k),ruby_array:bracket_get(k):根据键取得对应值(Ruby中的[])ruby_array:set(k, v),ruby_array:bracket_set(k, v):设置键对应的值(Ruby中的[]=)
Hashruby_hash:length(),ruby_hash:size():取得元素数(Ruby中的length,size)ruby_hash:get(k),ruby_hash:bracket_get(k):根据键取得对应值(Ruby中的[])ruby_hash:set(k, v),ruby_hash:bracket_set(k, v):设置键对应的值(Ruby中的[]=)ruby_hash:has_key(k),ruby_hash:include(k):是否包含键(Ruby中的has_key?,include?)ruby_hash:has_value(v):是否包含值(Ruby中的has_value?)ruby_hash:index(v):寻找能对应值的一个键,未找到则返回nil(Ruby中的index)ruby_hash:keys():返回包含的各键(Ruby中的keys)ruby_hash:values():返回包含的各值(Ruby中的values)
Methodruby_method:call(...):调用方法(Ruby中的call)
Procruby_proc:call(...):调用过程(Ruby中的call)
- 由于在初始化中使用了ffi库来包装RGSS的DLL中的
RGSSEval,这个项目只支持LuaJIT,很可能无法支持原生Lua 5.1。 - 在Lua中,数字只有一种数据类型
number,因此当从Lua来的数字要变成Ruby的Hash的键时,也只能当作Float浮点数处理,访问不到Integer类型的键。- 但是,Lua来的数字要变成Ruby的
Array的键时,数字到整数的转换能隐式自动完成。
- 但是,Lua来的数字要变成Ruby的
- 跨语言调用通常有一定性能损失。想要发挥充分的性能,最好减少跨越语言边界的次数。
- 例如,相比一次次在Lua中调用Ruby的方法,可能的话最好精简成在Lua中整理好指令,一次性交给Ruby后再将必要的信息一同返回。
- 在Lua中调用Ruby的方法的性能损失大于在Ruby中调用Lua的函数的性能损失。
- 域外创音
<https://github.com/rinkaa, https://rpg.blue/home.php?mod=space&uid=2712193, kaitensekai@qq.com>(c) 2024 - 岚风雷
<https://github.com/gqxastg, https://rpg.blue/home.php?mod=space&uid=216371>(c) 2024
MIT