【第三篇】C#调用lua文件
获取一个全局基本数据类型
使用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文件的更多相关文章
- 微信支付 第三篇 微信调用H5页面进行支付
上一篇讲到拿到了 预支付交易标识 wx251xxxxxxxxxxxxxxxxxxxxxxxxxxxxx078700 第四步,是时候微信内H5调起支付了! 先准备网页端接口请求参数列表 微信文档中已经明 ...
- Python 第三篇(上):python文件基础操作、json模块、lambda、map、filter、reduce和函数位置参数
python一切皆对象,linux一切皆文件,python操作文件是很常见的O/I操作,其内置来open()函数可以完成文件的基本操作: 一:使用内置open()函数操作文件,基本语法如下: with ...
- 第三篇--如何修改exe文件版本号和文件信息
控制台程序添加版本信息方法: 项目右键 Add-->Resource-->选择Version-->new,然后就可以修改里面的信息了,重新编译一下就OK.
- Lua与C++交互初探之C++调用Lua
Lua与C++交互初探之C++调用Lua 自从学习了lua这个脚本语言之后,无时不想着将他与c/c++联系起来,看看他真正的威力.奈何水平有限,网上找的代码无论怎样都无法运行成功.我知道是我少了某一步 ...
- [置顶] android利用jni调用第三方库——第三篇——编写库android程序整合第三方库libhello.so到自己的库libhelloword.so
0:前言: 在第二篇中,我们主要介绍了丙方android公司利用乙方C++公司给的动态库,直接调用库中的方法,但是这样方式受限于: 乙方C++公司开发的动态库是否符合jni的规范,如果不规范,则不能直 ...
- JDFS:一款分布式文件管理系统,第三篇(流式云存储)
一 前言 看了一下,距离上一篇博客的发表已经过去了4个月,时间过得好快啊.本篇博客是JDFS系列的第三篇博客,JDFS的目的是为了实现一个分布式的文件管理系统,前两篇实现了基本的上传.下载功能,但是那 ...
- Python开发【第三篇】:Python基本之文件操作
Python基本之文本操作 一.初识文本的基本操作 在python中打开文件有两种方式,即:open(...) 和 file(...) ,本质上前者在内部会调用后者来进行文件操作,推荐使用 open ...
- 分析RAC下一个SPFILE整合的三篇文章的文件更改
大约RAC下一个spfile分析_整理在_2014.4.17 说明:文章来源于网络 第一篇:RAC下SPFILE文件改动 在RAC下spfile位置的改动与单节点环境不全然一致,有些地方须要特别注意, ...
- 初学Python——文件操作第三篇
一.引言 什么?有了第二篇文件操作还不够?远远不够!而且在读完第三篇文件操作还是不够.关于文件的操作,后续的学习中将不断学习新的操作方式,使用更加合适的方法. 进入正题,上一篇讲到,Python对文件 ...
随机推荐
- pycharm破解码
今天又遇到了pycharm注册码失效的问题: 找到了一个好用的破解教程,为了能够尽快的使用,我用的是注册码的方式 教程链接:https://www.cnblogs.com/yuuje/p/101009 ...
- 漏洞利用:验证绕过,XSS利用,Cookic盗用,文件上传
1. 文件上传 低级别 写好上传的内容 选择好上传的文件 上传成功. 测试:访问文件,执行代码 中级别 修改文件后缀为png 上传该文件 抓包修改文件后缀为php,然后允许数据包通过. 上传 ...
- 快乐编程大本营【java语言训练班】 6课:用java的对象和类编程
快乐编程大本营[java语言训练班] 6课:用java的对象和类编程 第1节. 什么是对象和类 第2节. 对象的属性和方法 第3节. 类的继承 第4节. 使用举例:创建类,定义方法,定义属性 第5节. ...
- 3.部署场景1:带有遗留的Open vSwitch
部署场景1:带有遗留的Open vSwitch 此场景描述了使用带有Open vSwitch(OVS)的ML2插件的OpenStack网络服务的(基本)实现. 遗留的实现通过为普通用户提供一种方法来管 ...
- Java类加载器和双亲委派机制
前言 之前详细介绍了Java类的整个加载过程(类加载机制详解).虽然,篇幅较长,但是也不要被内容吓到了,其实每个阶段都可以用一句话来概括. 1)加载:查找并加载类的二进制字节流数据. 2)验证:保证被 ...
- Windows下SVN权限配置
Windows下SVN权限配置 按照前面的教程装完1.6.1版以后,当svnadmin create D;\svn创建仓库后,应该在仓库目录下的config目录有3个文件— auth ...
- 使用IntelliJ IDEA创建Maven工程
1. 新建项目(点击“+ Create New Project”): 2. 选择Maven,不必选择项目骨架,直接点击Next 按钮即可: 3. 输入项目名称,选择项目位置,输入组织名称,模块名称,项 ...
- SPH液面重构过程中的问题
使用粒子方法进行流体特效模拟需要进行液面重构,构造出流体的自由表面,液面重构方法也是一个独立的研究方向,针对其的研究已经有了很多成果,包括液面的平滑度.精度和并行效率等. 在这里,主要是记录一下我在液 ...
- Java程序员必备英文单词
列表中共有769个单词,这些单词是从JDK.Spring.SpringBoot.Mybatis的源码中解析得到,按照在源码中出现的频次依次排列,页面中的单词是出现频次大于1000的.单词的音标.翻译结 ...
- 苹果系统iOS、macOS应用管理机制
iOS.macOS系统应用管理机制 苹果系统包括:iOS.macOS.watchOS.tvOS.应用软件的生命周期为:开发.上线.安装.使用.卸载.这篇文档将从应用生命周期的各个环节介绍苹果系统对应用 ...