获取一个全局基本数据类型

  使用LuaEnv.Global.Get<T>("name")就可以    

 var str = luaEnv.Global.Get<string>("str");
var num1 = luaEnv.Global.Get<int>("num1");

访问一个全局table

  方法1. 映射到普通class和sturct

 -- table
gameLanguage={str1 = "C#语言", str2 = "lua语言", str3 = "C++语言"}
    public class GameLanguage
{
public string str1;
public string str2;
public string str3;
} private void CallLuaTableByClass()
{
GameLanguage gameLanguage = luaEnv.Global.Get<GameLanguage>("gameLanguage");
Debug.Log("[使用类映射]str1: " + gameLanguage.str1);
Debug.Log("[使用类映射]str2: " + gameLanguage.str2);
Debug.Log("[使用类映射]str3: " + gameLanguage.str3);
gameLanguage.str1 = "我是修改后的内容";
luaEnv.DoString("print('修改后str1的值='..gameLanguage.str1)");
}

  注释:

    这个过程是值拷贝,如果class比较复杂代价会比较大(较消耗性能)。而且修改class字段值不会同步到table,反过来也不会。这种方式可以通过把类型添加到GCPotimize生成减低开销

  方法2. 使用interface来进行映射【推荐】

gameUser = {
name = "XC",
age = ,
ID = "", Speak = function()
print("lua玩家在讨论中");
end, Walking = function()
print("lua玩家在走路中");
end, Calulation = function(this, num1, num2) --说明:this这里命名可以任意,表示当前对象(即:gameUser)
return this.age + num1 + num2;
end,
}
    [CSharpCallLua]
public interface IGameUser
{
string name { get; set; }
int age { get; set; }
string ID { get; set; } void Speak();
void Walking();
int Calulation(int num1, int num2);
} private void CallLuaComplateTableByInterface()
{
IGameUser gameUser = luaEnv.Global.Get<IGameUser>("gameUser"); Debug.Log("[使用接口映射]name: " + gameUser.name);
Debug.Log("[使用接口映射]age: " + gameUser.age);
Debug.Log("[使用接口映射]ID: " + gameUser.ID); gameUser.Speak();
gameUser.Walking();
var result = gameUser.Calulation(, );
Debug.Log("经过lua计算,结果=" + result); gameUser.name = "XCC";
luaEnv.DoString("print('修改后name的值='..gameUser.name)");
}

  注释:

    这种方式依赖于生成代码(接口需要添加标签【CSharpCallLua】如果没生成代码会抛InvalidCastException异常)get对应table字段,set可以访问修改lua函数。这种方式为引用拷贝,适合用于复杂表

    

  方法3. 使用Dictionary<key, value> 和 List<>映射简单表

gameLanguage = {str1 = "C#语言", str2 = "lua语言", str3 = "C++语言"}
gameLanguageList = {"C#语言", "lua语言", "C++语言"}
    private void CallLuaTableByDictionary()
{
var dicGameLanguage = luaEnv.Global.Get<Dictionary<string, object>>("gameLanguage"); // 映射一个简单表 foreach (string key in dicGameLanguage.Keys)
{
Debug.Log("输出Dictionary中的所有语言" + dicGameLanguage[key]);
}
} private void CallLuaTableByList()
{
var list = luaEnv.Global.Get<List<object>>("gameLanguageList"); for (int i = ; i < list.Count; i++)
{
Debug.Log("输出List中的所有语言" + list[i]);
}
}

  注释:这种方式只能映射简单的表。优点是编写简单,效率高。

  方法4. 使用LuaTable映射

    private void CallLuaTableByLuaTable()
{
var gameUser = luaEnv.Global.Get<LuaTable>("gameUser"); Debug.Log("name = " + gameUser.Get<string>("name"));
Debug.Log("age = " + gameUser.Get<int>("age"));
Debug.Log("ID = " + gameUser.Get<string>("ID")); var speak = gameUser.Get<LuaFunction>("Speak");
speak.Call(); var walking = gameUser.Get<LuaFunction>("Walking");
walking.Call(); var calulation = gameUser.Get<LuaFunction>("Calulation");
var objArray = calulation.Call(gameUser, , );
Debug.Log("输出结果 = " + objArray[]);
}

  注释:

  这种方式好处是不需要生成代码,但问题是比较慢(即:效率低)比interface方式慢一个数量级,比如没有类型检查

  因为效率低,不推荐常用,适合用在一些很复杂但是使用频率很低的情况下,能不用就不用。

访问一个全局的function

  方法1. 使用delegage访问

-- 定义单独的lua函数
function ProcMyFunc1()
print("procMyFunc1 无参函数");
end function ProcMyFunc2(num1, num2)
print("procMyFunc2 两个函数 num1+num2="..num1+num2);
end function ProcMyFunc3(num1, num2)
print("procMyFunc3 具备返回值的函数");
return num1+num2;
end function ProcMyFunc4(num1, num2, num3)
print("procMyFunc4 三个函数 num1+num2+num3="..num1+num2+num3);
end function ProcMyFunc5(num1, num2)
local result = num1+num2;
print("procMyFunc4 具备多个返回值的函数");
return num1,num2,result;
end
    // 自定义委托
public delegate void delegateAdding(int num1, int num2); private void CallLuaFunctionByDelegage()
{
// 使用action直接获取没有参数的函数
var action1 = luaEnv.Global.Get<Action>("ProcMyFunc1");
action1(); // 使用自定义委托调用具备两个输入参数的函数
var action2 = luaEnv.Global.Get<delegateAdding>("ProcMyFunc2");
action2(, );
}

  多返回值处理方法

  定义全局的delegate

[CSharpCallLua]
public delegate void delegateAddingMultiReturn(int num1, int num2, out int res1, out int res2, out int res3); [CSharpCallLua]
public delegate void delegateAddingMultiReturnRef(ref int num1, ref int num2, out int res3);
    // 使用delegate访问多返回值得luafunction
private void CallLuaFunctionByDelegateMultiReturn()
{
// 得到lua中的具有多个返回值的函数(通过委托out关键字来进行映射)
act1 = luaEnv.Global.Get<delegateAddingMultiReturn>("ProcMyFunc5"); // 得到lua中的具有多个返回值的函数(通过委托ref关键字来进行映射)
act2 = luaEnv.Global.Get<delegateAddingMultiReturnRef>("ProcMyFunc5"); // 输出返回结果
int intOutRes1 = ;
int intOutRes2 = ;
int intOutRes3 = ;
act1(, , out intOutRes1, out intOutRes2, out intOutRes3);
Debug.Log(string.Format("res1={0}, res2={1}, res3={2}", intOutRes1, intOutRes2, intOutRes3)); int intResult = ;
int intRef1 = ;
int intRef2 = ;
act2(ref intRef1, ref intRef2, out intResult);
Debug.Log(string.Format("输入1={0}, 输入2={1}, 输出={2}", intRef1, intRef2, intResult));
}

  注释:

  优点:官方推荐方式,性能好,类型安全

  缺点:(含有out与ref关键字delegate)要生成代码(如果没有生成会抛InvalidCastException异常)

  注意:

  1. 含有out与ref关键字委托也需要添加标签[CSharpCallLua]

  2. 委托引用后,退出luaEnv前,需要释放委托引用,否则会报错

  3. 对于Unity与C#中复杂类型API,必须加入xLua的配置文件,经过生成代码后才能正确使用。例如:Action<int, int, int> 、Func<int, int, int>等

  方法2. 使用LuaFunction实现

    private void CallLuaFunctionByLuaFunction()
{
var luaFunc1 = luaEnv.Global.Get<LuaFunction>("ProcMyFunc1");
var luaFunc2 = luaEnv.Global.Get<LuaFunction>("ProcMyFunc2");
var luaFunc3 = luaEnv.Global.Get<LuaFunction>("ProcMyFunc3");
// 调用具有多返回数值
var luaFunc5 = luaEnv.Global.Get<LuaFunction>("ProcMyFunc5"); luaFunc1.Call();
luaFunc2.Call(, ); var result = luaFunc3.Call(, );
Debug.Log("调用ProcMyFunc3, 结果为:" + result[]); var result5 = luaFunc5.Call(, );
Debug.Log(string.Format("测试多返回数值 res1={0}, res2={1}, res3={2}", result5[], result5[], result5[]));
}

  注释:

  优点:无需生成代码

  缺点:性能不高,不推荐

  这种方式使用起来很简单,LuaFcuntion上有个变参的Call函数,可以传任意类型,任意个数的参数,返回值是object的数组,对应于lua的多返回值

官方使用建议:

  1. 访问lua全局数据,特别是table以及function,代价比较大,建议尽量少做,比如在初始化时把要调用的lua functio获取一次(映射到delegate)后,保存下来,后续直接调用该delegate即可。table也类似。

  2. 如果lua实现的部分都以delegate和interface的方式提供,使用方可以完全和xLua解耦,由一个专门的模块负责xLua的初始化以及delegate、interface的映射,然后把这些delegate和interface设置到要用到他们的地方

最新文章

  1. Windows平板优化设置
  2. (转) 站在C#和JS的角度细谈函数式编程与闭包
  3. 配置DNS实验一例
  4. meta-analysis 到底是什么个意思类?
  5. JavaScript系列:再巩固-原型链
  6. Django数据库设计中字段为空的方式
  7. linux查看内存和回收内存
  8. jquery.fn.extend与jquery.extend(转)
  9. python中文注释及输出出错
  10. JSON在线解析,新版本JSON在线解析
  11. 【Java基础】反射机制
  12. nginx取结构体地址
  13. HIT创业感言:只有长寿的企业才有持续价值
  14. elementUI vue v-model的修饰符
  15. SQL Server2016导出数据表数据
  16. Java基础实践一:for关键字的实现原理
  17. Windows 10正式版的历史版本
  18. WebApi 文档Swagger
  19. 检查oracle用户默认密码的账户
  20. JDBC的介绍

热门文章

  1. HanLP《自然语言处理入门》笔记--1.新手上路
  2. WEB打印控件LODOP的使用
  3. Web 开发工具类(1): CookieUtils
  4. 1755: N相关孪生素数
  5. 场景7:带有Linux网桥的提供商网络
  6. [apue] 书中关于伪终端的一个纰漏
  7. tornado自定义分页扩展
  8. 不用&#39;+&#39;完成a + b
  9. TCP加速方式
  10. 解决Python2.7的UnicodeEncodeError: &#39;ascii&#39; codec can&#39;t encode异常错误