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

  使用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设置到要用到他们的地方

【第三篇】C#调用lua文件的更多相关文章

  1. 微信支付 第三篇 微信调用H5页面进行支付

    上一篇讲到拿到了 预支付交易标识 wx251xxxxxxxxxxxxxxxxxxxxxxxxxxxxx078700 第四步,是时候微信内H5调起支付了! 先准备网页端接口请求参数列表 微信文档中已经明 ...

  2. Python 第三篇(上):python文件基础操作、json模块、lambda、map、filter、reduce和函数位置参数

    python一切皆对象,linux一切皆文件,python操作文件是很常见的O/I操作,其内置来open()函数可以完成文件的基本操作: 一:使用内置open()函数操作文件,基本语法如下: with ...

  3. 第三篇--如何修改exe文件版本号和文件信息

    控制台程序添加版本信息方法: 项目右键 Add-->Resource-->选择Version-->new,然后就可以修改里面的信息了,重新编译一下就OK.

  4. Lua与C++交互初探之C++调用Lua

    Lua与C++交互初探之C++调用Lua 自从学习了lua这个脚本语言之后,无时不想着将他与c/c++联系起来,看看他真正的威力.奈何水平有限,网上找的代码无论怎样都无法运行成功.我知道是我少了某一步 ...

  5. [置顶] android利用jni调用第三方库——第三篇——编写库android程序整合第三方库libhello.so到自己的库libhelloword.so

    0:前言: 在第二篇中,我们主要介绍了丙方android公司利用乙方C++公司给的动态库,直接调用库中的方法,但是这样方式受限于: 乙方C++公司开发的动态库是否符合jni的规范,如果不规范,则不能直 ...

  6. JDFS:一款分布式文件管理系统,第三篇(流式云存储)

    一 前言 看了一下,距离上一篇博客的发表已经过去了4个月,时间过得好快啊.本篇博客是JDFS系列的第三篇博客,JDFS的目的是为了实现一个分布式的文件管理系统,前两篇实现了基本的上传.下载功能,但是那 ...

  7. Python开发【第三篇】:Python基本之文件操作

    Python基本之文本操作 一.初识文本的基本操作 在python中打开文件有两种方式,即:open(...) 和  file(...) ,本质上前者在内部会调用后者来进行文件操作,推荐使用 open ...

  8. 分析RAC下一个SPFILE整合的三篇文章的文件更改

    大约RAC下一个spfile分析_整理在_2014.4.17 说明:文章来源于网络 第一篇:RAC下SPFILE文件改动 在RAC下spfile位置的改动与单节点环境不全然一致,有些地方须要特别注意, ...

  9. 初学Python——文件操作第三篇

    一.引言 什么?有了第二篇文件操作还不够?远远不够!而且在读完第三篇文件操作还是不够.关于文件的操作,后续的学习中将不断学习新的操作方式,使用更加合适的方法. 进入正题,上一篇讲到,Python对文件 ...

随机推荐

  1. Mybatisplus代码生成器主类CodeGenerator配置

    //代码自动生成public class CodeGenerator { /** * <p> * 读取控制台内容 * </p> */ public static String ...

  2. JVM 面试题汇总

    JVM 面试题汇总 1.什么是 JVM?它有什么作用? 答:JVM 是 Java Virtual Machine(Java 虚拟机)的缩写,顾名思义它是一个虚拟计算机,也是 Java 程序能够实现跨平 ...

  3. 实验21:IPv6

    九.IPv6 1.IPv6(RIP) 实验目的:熟悉IPv6的配置,并经过动态路由协议RIP,使三台路由器相互通讯设备需求:3640三台实验过程: xdbr_R1#sh runipv6 unicast ...

  4. gRPC in ASP.NET Core 3.x -- Protocol Buffer(2)Go语言的例子(下)

    第一篇文章(大约半年前写的):https://www.cnblogs.com/cgzl/p/11246324.html gRPC in ASP.NET Core 3.x -- Protocol Buf ...

  5. GDI+如何判断一个点是否在区域内

    https://msdn.microsoft.com/en-us/library/windows/desktop/ms533826(v=vs.85).aspx The purpose of hit t ...

  6. 应用层vc实现三种文件监视方法

    http://hi.baidu.com/sadusaga/item/daa0d4b764c6dd76254b09cc http://bbs.csdn.net/topics/280032788 http ...

  7. 透彻分析和解决一切javaWeb项目乱码问题

    前言 乱码是我们在程序开发中经常碰到且让人头疼的一件事,尤其是我们在做javaweb开发,如果我们没有清楚乱码产生的原理,碰到乱码问题了就容易摸不着头脑,无从下手. 乱码主要出现在两部分,如下: 第一 ...

  8. 在4K屏下以超过VMWare默认的最高分辨率运行Linux系统

    前言 4K 屏,有其优点也有其弊端.优点就是分辨率高,字体和图标看起来如丝一般顺滑:缺点就是字体和图标小,费眼睛.解决这个缺点的方法也很简单粗暴,就是将系统的显示比例放大.在高分屏不很普及的时候,无论 ...

  9. Airtest自动化测试工具介绍

    官方网站:http://airtest.netease.com/ Airtest IDE: 跨平台的UI自动化测试编辑器,适用于游戏和App,详细参见官网文档:http://airtest.netea ...

  10. JFrame的BorderLayout

    JFrame的默认布局就是BorderLayout,即将一个窗体划分为东西南北中五个板块. 如果往其中添加组件,中间面板大小随窗体大小变化,其余部分根据添加的组件的大小自适应. 容器变高,则North ...