【第三篇】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对文件 ...
随机推荐
- Spring Boot入门简介-Maven配置
一.简介 -- 简化Spring应用开发的一个框架: -- 整个Spring技术栈的一个大整合: -- J2EE开发的一站式解决方案. 二.背景: ① J2EE笨重的开发.繁多的配置.低下的开发效率. ...
- WTL Hello World
构建最简单的WTL Hello World程序,基于:WTL91_5321_Final + VS2013 + WIN7 添加->新建项目 为了简单起见,我们删除一些button和对应的处理代码( ...
- 【WPF学习】第四十章 画刷
画刷填充区域,不管是元素的背景色.前景色以及边框,还是形状的内部填充和笔画(Stroke).最简单的画刷类型是SolidColorBrush,这种画刷填充一种固定.连续的颜色.在XAML中设置形状的S ...
- 使用Apache服务器实现Nginx反向代理
实验环境:centos7 注:因为本次实验在同一台服务器上,Apache与Nginx同为80端口,所以改Apache端口为60 1 配置Nginx服务器: 编辑Nginx配置文件,写入以下内容 loc ...
- 《Head first设计模式》之工厂模式
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个.工厂方法让类把实例化推迟到了子类. 预定披萨 假设你有一个披萨店,预定披萨的代码可能是这么写的: Pizza orderPizz ...
- qt creator源码全方面分析(2-10-1)
目录 Getting and Building Qt Creator 获取Qt 获取和构建Qt Creator Getting and Building Qt Creator 待办事项:应该对此进行扩 ...
- VFP检测SQL Server的五个实例代码
** 需要指出的是,无论下面哪种方式的代码,都需要打开本机的网络共享,否则找不到SQL服务器** 例一 ************************************************ ...
- gitlab(五):一个开发流程实例
一个多人开发的样例 开发的流程我们都知道: 根据项目版本,创建里程碑,创建开发的issue,分配给dev dev从master clone代码,创建分支就行开发,开发完成之后,提交分支 dev给开发负 ...
- docker 修改 bridge网桥网段
首先停止正在使用的 Docker 服务: $ sudo service docker stop 接着删除 Docker 默认网桥 docker0 : $ sudo ip link set dev do ...
- Linux文本三剑客
grep 文本过滤工具. 作用: 文本搜索工具,根据用户指定的行进行匹配检查,打印匹配到的行. 模式: 由正则表达式字符及文本字符所编写的过滤条件. grep的使用 语法: grep [OPTION ...