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

  使用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. 线程池之 Executors

    线程池之 Executors + 面试题 线程池的创建分为两种方式:ThreadPoolExecutor 和 Executors,上一节学习了 ThreadPoolExecutor 的使用方式,本节重 ...

  2. Message: 'chromedriver' executable needs to be available in the path.

    环境:windows10 python:3.7.3 已经把 executable.exe 添加到了环境变量中,但还是会提示以上错误. 解决办法: from selenium import webdri ...

  3. CAD制图系列之如何画内切圆

    今天我将记录我们如何画一个大圆,里面均匀内切四个小圆 具体步骤如下: 第一步:首先,先画一个十字架,用于作为轴 第二步:以十字架交点为圆心,画一个半径为25的圆 第三步:以中点为坐标画四十五度斜线,方 ...

  4. webpack入门系列1

    一.什么是webpack?为什么要使用它? Webpack 是一个前端资源加载/打包工具.它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源. 为什么我们要使用它呢?因 ...

  5. 数百个 HT 工业互联网 2D 3D 可视化应用案例分享 - 2019 篇

    继<分享数百个 HT 工业互联网 2D 3D 可视化应用案例>2018 篇,图扑软件定义 2018 为国内工业互联网可视化的元年后,2019 年里我们与各行业客户进行了更深度合作,拓展了H ...

  6. ListFragment 使用ListView and 自定义Adapter

    在开发过程中经常使用Tabs + ListFragment 作为表现形式. ListFragment 中加入ListView显示方式很容易. [java] view plaincopy package ...

  7. Codeforces_814

    A.b序列从大到小填a序列中的0,在判断. #include<bits/stdc++.h> using namespace std; ],b[]; int main() { ios::sy ...

  8. 在form子句中使用子查询时的注意事项

    今天中午为了弄清这个问题,本人真的是头都搞大了!最后明白了一点,在from子句中使用子查询是,一定要将临时表的别名带上,否则会灰常痛苦!!!

  9. 超长可视化指南!带你理清K8S部署的故障排查思路,让bug无处遁形

    本文将帮助你厘清在Kubernetes中调试 deployment的思路.下图是完整的故障排查思路,如果你想获得更清晰的图片,请在公众号后台(RancherLabs)回复"troublesh ...

  10. 《Redis5.x入门教程》之准备工作、数据类型

    关注公众号:CoderBuff,回复"redis"获取<Redis5.x入门教程>完整版PDF. 第一章 · 准备工作 Redis安装 Redis5.0.7下载地址:h ...