找回密码
 立即注册
查看: 209|回复: 0

xLua学习之路(四) ------ Lua调用C#

[复制链接]
发表于 2021-8-13 09:35 | 显示全部楼层 |阅读模式
1.new C#对象

你在C#这样new一个对象:
     var newGameObj = new UnityEngine.GameObject();
对应到Lua是这样:
     local newGameObj = CS.UnityEngine.GameObject() --新建一个对象
基本类似,除了:
1、lua里头没有new关键字;
2、所有C#相关的都放到CS下,包括构造函数,静态成员属性、方法;
如果有多个构造函数呢?放心,xlua支持重载,比如你要调用GameObject的带一个string参数的构造函数,这么写:
      local newGameObj2 =CS.UnityEngine.GameObject('helloworld')
2.访问C#静态属性,方法

读静态属性
   CS.UnityEngine.Time.deltaTime
写静态属性
   CS.UnityEngine.Time.timeScale = 0.5
调用静态方法
   CS.UnityEngine.GameObject.Find('helloworld')
小技巧:如果需要经常访问的类,可以先用局部变量引用后访问,除了减少敲代码的时间,还能提高性能
   local GameObject = CS.UnityEngine.GameObject  
   GameObject.Find('helloworld')  --访问静态方法
3.访问C#成员属性,方法

local gameObject = CS.UnityEngine.GameObject
local camera = gameObject.Find("Main Camera")  --得到类的对象

读成员属性
   camera .name
写成员属性
   camera.name = "update by lua"
调用成员方法(使用.不会默认传this)
  local cameraCom= camera.GetComponent(camera,"Camera")  --因此要将本身传过去
注意:调用成员方法,第一个参数需要传该对象,建议用冒号语法,如下
  local cameraCom= camera:GetComponent("Camera")


4.父类属性,方法

xlua支持(通过派生类)访问基类的静态属性,静态方法,(通过派生类实例)访问基类的成员属性,成员方法
5.参数的输入输出属性(out,ref)

Lua调用的参数处理规则:C#的普通参数算一个输入形参,ref修饰的算一个输入形参,out不算,然后从左往右对应lua 调用测的实参列表;
Lua调用的返回值处理规则:C#函数的返回值(如果有的话)算一个返回值,out算一个返回值,ref算一个返回值,然后从左往右对应lua的多返回值。
6.重载方法

直接通过不同的参数类型进行重载函数的访问,例如:
testobj:TestFunc(100)
testobj:TestFunc('hello')
将分别访问整数参数的TestFunc和字符串参数的TestFunc。
注意:xlua只一定程度上支持重载函数的调用,因为lua的类型远远不如C#丰富,存在一对多的情况,比如C#的int,float,double都对应于lua的number,上面的例子中TestFunc如果有这些重载参数,第一行将无法区分开来,只能调用到其中一个(生成代码中排前面的那个)
7.参数带默认值的方法

        和C#调用有默认值参数的函数一样,如果所给的实参少于形参,则会用默认值补上。
8.可变参数方法

对于C#的如下方法:
  void VariableParamsFunc(int a, paramsstring[] strs)
可以在lua里头这样调用:
  testobj:VariableParamsFunc(5, 'hello', 'john')  
9.使用Extension methods(扩展方法)

         在C#里定义了,lua里就能直接使用。
10.泛化(模版)方法

        不直接支持,可以通过Extension methods功能进行封装后调用。
11.枚举类型

枚举值就像枚举类型下的静态属性一样。
  testobj:EnumTestFunc(CS.Tutorial.TestEnum.E1)
上面的EnumTestFunc函数参数是Tutorial.TestEnum类型的
另外,如果枚举类加入到生成代码的话(加上[LuaCallCSharp],lua调用C#),枚举类将支持__CastFrom方法,可以实现从一个整数或者字符串到枚举值的转换,例如:
  CS.Tutorial.TestEnum.__CastFrom(1)
  CS.Tutorial.TestEnum.__CastFrom('E1')
12.delegate使用(调用,+,-)

C#的delegate调用:和调用普通lua函数一样
+操作符:对应C#的+操作符,把两个调用串成一个调用链,右操作数可以是同类型的C# delegate或者是lua函数。
-操作符:和+相反,把一个delegate从调用链中移除。
Ps:delegate属性可以用一个luafunction来赋值。
13.event

比如testobj里头有个事件定义是这样:public event Action TestEvent;
lua中增加事件回调:
  testobj:TestEvent('+', lua_event_callback)
lua中移除事件回调
  testobj:TestEvent('-', lua_event_callback)
14.64位整数支持

Lua53版本64位整数(long,ulong)映射到原生的64未整数,而luaji版本t,相当于lua5.1的标准,本身不支持64位,xlua做了个64位支持的扩展库,C#的long和ulong都将映射到userdata:
1、支持在lua里头进行64位的运算,比较,打印
2、支持和lua number的运算,比较
3、要注意的是,在64扩展库中,实际上只有int64,ulong也会先强转成long再传递到lua,而对ulong的一些运算,比较,我们采取和java一样的支持方式,提供一组API,详情请看API文档。
15.C#复杂类型和table的自动转换

对于一个有无参构造函数的C#复杂类型,在lua侧可以直接用一个table来代替,该table对应复杂类型的public字段有相应字段即可,支持函数参数传递,属性赋值等,例如:
C#下B结构体(class也支持)定义如下:
  1. public struct A
  2. {
  3.     public int a;
  4. }
  5. public struct B
  6. {
  7.     public A b;
  8.     public double c;
  9. }
复制代码
某个类有成员函数如下:
       void Foo(B b)
在lua可以这么调用
obj:Foo({b = {a =100}, c = 200})   --{a = 100}相当于A,{a={100},c=200相当于B}
16.获取类型(相当于C#的typeof)

比如要获取UnityEngine.ParticleSystem类的Type信息,lua中可以这样
typeof(CS.UnityEngine.ParticleSystem) --typeof前面不需要加CS等命名空间
17.“强”转

lua没类型,所以不会有强类型语言的“强转”,但有个有点像的东西:告诉xlua要用指定的生成代码去调用一个对象,这在什么情况下能用到呢?有的时候第三方库对外暴露的是一个interface或者抽象类,实现类是隐藏的,这样我们无法对实现类进行代码生成。该实现类将会被xlua识别为未生成代码而用反射来访问,如果这个调用是很频繁的话还是很影响性能的,这时我们就可以把这个interface或者抽象类加到生成代码,然后指定用该生成代码来访问
  cast(calc, typeof(CS.Tutorial.Calc)) --lua调用C#方法传参数的时候可能会涉及到类型转换,因此使用强转,calc是要强转的对象,typeof(CS.Tutorial.Calc)强转的目标类型
上面就是指定用CS.Tutorial.Calc的生成代码来访问calc对象。
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 09:21 , Processed in 0.064467 second(s), 22 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表