使用lua作为Erlang的业务插件,用来处理一些配置性的变化,支持非调度器线程池来执行lua。ailua使用的是nif模式直接内嵌到Erlang的虚拟机中,如果lua代码过于复杂的话造成崩溃或内存泄漏, 则会引起Erlang虚拟机崩溃和内存泄漏
因为lua需要readline这个库,所以需要预先安装readline开发库。
master分支,使用的是lua5.3版本,使用的默认配置,并未使用erlang的内存分配器优化lua的内存分配
luajit分支,使用的是luajit-2.0.5版本,默认打开jit模式,支持lua5.1版本的语法
最少为1个线程,默认会创建Erlang调度器线程的数量一半新线程作为异步线程池,目前不 支持指定线程数量的方法。
ailua 从tag-0.3.0及tag-0.3.0-jit后就不再支持线程池,改为使用Erlang自身的Dirty Schedules来做承载,可以配合poolboy或者 ailib中的pool相关模块使用
{ok,Ref} = ailua:new()
带有初始化路径
{ok,CWD} = file:get_cwd(),
P = erlang:list_to_binary(filename:join(CWD,"./?.lua")),
{ok,Ref} = ailua:new(<<";",P/binary>>).
Ref会绑定一个lua虚拟机,该Ref会随着创建进程的退出而释放
创建Ref的Erlang进程崩溃后,该Ref的行为如下
- 如果该Ref有异步操作,会在最后一个异步操作后释放该Ref绑定的lua虚拟机
- 如果该Ref没有任何异步操作,则立刻释放该Ref绑定的lua虚拟机
同步方法
ok = ailua:dofile(Ref,FileName)
异步方法
CallerRef = make_ref(),
CallerPid = self(),
ok = ailua:dofile_async(L,CallerRef,CallerPid,FileName)
同步方法
ok = ailua:call(Ref,FunctionName,Args)
异步方法
CallerRef = make_ref(),
CallerPid = self(),
ok = ailua:async_call(L,CallerRef,CallerPid,FunctionName,Args)
其中FunctionName为字符串,Arags为列表
- lua脚本需要使用绝对路径,如果想使用相对路径,需要自己设置lua的package相关路径
- 目前Erlang到lua传值不支持tuple和proplists,不支持Erlang高阶函数传入lua
- Erlang到lua传值,字符串使用binary而非list
- Erlang到lua传值,如果字符串是list,则会被映射到lua的table上
- Erlang到lua传值,原子值true,false会自动转化成lua的boolean型,undefined和null会自动转化成lua的nil值
- Erlang到lua传值,如果整形大于了18446744073709551615,默认方法会将该整形转化成double
- Erlang到lua传值,如果整形小于了-9223372036854775808,默认方法会将该整形转化成double
- lua到Erlang传值,boolean会自动变更为atom,nil会自动变更为erlang的undefined
- lua表的元表中请勿设置_ERL_MAP为true字段,该字段是ailua用来区分lua回传给Erlang的table是list还是map
- lua回传map的时候,请使用to_erl_map(map)来进行转化
- 目前不支持lua的userdata,function等比较特殊类型
- 请避免在lua脚本中执行print操作,ailua并为处理lua的输出,这些输出会直接输出到stderr上
- 不建议使用lua带so的依赖,不建议使用外部IO和lua的协作线程
ailua并未附带过多例子,但是仍有一个test.lua来进行测试
执行方式如下
make
erl -pa ./ebin
{ok,Ref} = ailua:new().
ok = ailua:dofile(Ref,"./test/test.lua").
ailua:call(Ref,"hi",[#{1 => "hi"}]).
ailua:call(Ref,"test:in_table",[1]).
ailua:call(Ref,"test.in_table2",[2]).