9.Unity调用ILRuntime-方法调用-ref和out方法调用
9.1 知识点
ref/out方法调用
ref/out方法调用概述
需要通过 IMethod
方法调用,并且需要使用无GC Alloc方法调用。
和其他函数不一样的地方是需要先压入
ref
或out
参数的初始值。和其他函数调用写法一致,需要压入调用对象和各参数。
ref
和out
参数因为在一开始就压入了值,在这里需要压入它们的索引位置。ref
和out
参数压入参数引用索引值即可,从0开始。通过
Read
按顺序获取ref
/out
参数的值和返回值,返回值最后获取。
给Lesson4_Test添加ref/out方法,并重新生成
public float TestFun3(int i, ref List<int> list, out float f)
{
f = .5f;
list.Add(5);
for (int j = 0; j < list.Count; j++)
Debug.Log(list[j]);
return i + list.Count + f;
}
获取ref/out方法调用概述
ILRuntimeManager.Instance.StartILRuntime(() =>
{
AppDomain appDomain = ILRuntimeManager.Instance.appDomain;
//得到IType 通过他实例化一个指定的热更新工程中的类对象 (Lesson4_Test)
IType type = appDomain.LoadedTypes["HotFix_Project.Lesson4_Test"];
object obj = ((ILType)type).Instantiate(); //实例化Lesson4_Test对象
//需要通过IMethod方法调用
//并且需要使用无GC Alloc方法调用
IMethod methodName = type.GetMethod("TestFun3", 3);
List<int> list = new List<int>() { 1, 2, 3, 4 };
using (var method = appDomain.BeginInvoke(methodName))
{
//1.和其他函数不一样的地方
//需要先压入ref或out参数的初始值
//压入第一个ref参数的初始值
method.PushObject(list);
//压入第二个out参数的初始值 由于out参数不需要在外部初始化 所以压入null 即可
method.PushObject(null);
//2.和其它函数调用写法一致
//压入调用对象
method.PushObject(obj);
//压入各参数
method.PushInteger(100);
//3.ref和out因为在一开始就压入了值
//在这里需要压入他们的索引位置
//ref和out参数 压入参数引用索引值即可 从0开始
method.PushReference(0);
method.PushReference(1);
method.Invoke(); //1 2 3 4 5
//4.通过Read按顺序获取ref/out参数的值 和返回值,返回值最后获取
//获取ref参数
list = method.ReadObject<List<int>>(0);
//获取out参数
float f = method.ReadFloat(1);
//获取函数返回值
float returnValue = method.ReadFloat();
print("ref参数 list的长度 " + list.Count); //ref参数 list的长度 5
print("out参数:" + f); //out参数:0.5
print("函数返回值:" + returnValue); //函数返回值:105.5 因为100+5+0.5
}
});
总结
ref/out方法只能通过无GC Alloc方法调用
using BeginInvoke
,push
,invoke
,read
,ubpir
方式。在调用时多了三个步骤:
- 需要先压入
ref
或out
参数的初始值。 - 压入参数环节压入引用索引值。
- 通过
Read
按顺序获取ref
、out
参数,返回值最后获取。
- 需要先压入
9.2 知识点代码
Lesson4_Test
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace HotFix_Project
{
class Lesson4_Test
{
#region 成员变量
private string str;
#endregion
#region 成员属性
public string Str
{
get
{
return str;
}
set
{
str = value;
}
}
#endregion
#region 构造函数
public Lesson4_Test()
{
}
public Lesson4_Test(string str)
{
this.str = str;
}
#endregion
#region 静态方法
public static void TestStaticFun()
{
Debug.Log("无参静态方法");
}
public static int TestStaticFun2(int i)
{
Debug.Log("有参静态方法" + i);
return i + 10;
}
#endregion
#region 成员方法
public void TestFun()
{
Debug.Log("无参无返回值 成员方法调用");
}
public int TestFun2(int i)
{
Debug.Log("有参有返回值 成员方法调用");
return 10 + i;
}
#endregion
#region 重载方法
public void TestFun(int i)
{
Debug.Log("重载函数1,传进来的参数是" + i);
}
public void TestFun(float f)
{
Debug.Log("重载函数2,传进来的参数是" + f);
}
#endregion
#region ref和out方法
public float TestFun3(int i, ref List<int> list, out float f)
{
f = .5f;
list.Add(5);
for (int j = 0; j < list.Count; j++)
Debug.Log(list[j]);
return i + list.Count + f;
}
#endregion
}
}
Lesson09_Unity调用ILRuntime_方法调用_ref和out方法调用
using ILRuntime.CLR.Method;
using ILRuntime.CLR.TypeSystem;
using ILRuntime.Runtime.Enviorment;
using System.Collections;
using System.Collections.Generic;
using BaseFramework;
using UnityEngine;
public class Lesson09_Unity调用ILRuntime_方法调用_ref和out方法调用 : MonoBehaviour
{
void Start()
{
#region 复习 启动ILRuntime 创建类对象
ILRuntimeManager.Instance.StartILRuntime(() =>
{
AppDomain appDomain = ILRuntimeManager.Instance.appDomain;
//得到IType 通过他实例化一个指定的热更新工程中的类对象 (Lesson4_Test)
IType type = appDomain.LoadedTypes["HotFix_Project.Lesson4_Test"];
object obj = ((ILType)type).Instantiate(); //实例化Lesson4_Test对象
//需要通过IMethod方法调用
//并且需要使用无GC Alloc方法调用
IMethod methodName = type.GetMethod("TestFun3", 3);
List<int> list = new List<int>() { 1, 2, 3, 4 };
using (var method = appDomain.BeginInvoke(methodName))
{
//1.和其他函数不一样的地方
//需要先压入ref或out参数的初始值
//压入第一个ref参数的初始值
method.PushObject(list);
//压入第二个out参数的初始值 由于out参数不需要在外部初始化 所以压入null 即可
method.PushObject(null);
//2.和其它函数调用写法一致
//压入调用对象
method.PushObject(obj);
//压入各参数
method.PushInteger(100);
//3.ref和out因为在一开始就压入了值
//在这里需要压入他们的索引位置
//ref和out参数 压入参数引用索引值即可 从0开始
method.PushReference(0);
method.PushReference(1);
method.Invoke(); //1 2 3 4 5
//4.通过Read按顺序获取ref/out参数的值 和返回值,返回值最后获取
//获取ref参数
list = method.ReadObject<List<int>>(0);
//获取out参数
float f = method.ReadFloat(1);
//获取函数返回值
float returnValue = method.ReadFloat();
print("ref参数 list的长度 " + list.Count); //ref参数 list的长度 5
print("out参数:" + f); //out参数:0.5
print("函数返回值:" + returnValue); //函数返回值:105.5 因为100+5+0.5
}
});
#endregion
#region 知识点 ref/out方法调用
//需要通过IMethod方法调用
//并且需要使用无GC Alloc方法调用
//1.和其他函数不一样的地方
//需要先压入ref或out参数的初始值
//2.和其它函数调用写法一致
//压入调用对象
//压入各参数
//3.ref和out因为在一开始就压入了值
//在这里需要压入他们的索引位置
//ref和out参数 压入参数引用索引值即可 从0开始
//4.通过Read按顺序获取ref/out参数的值 和返回值,返回值最后获取
#endregion
#region 总结
//1.ref/out方法只能通过无GC Alloc方法调用 using BeginInvoke push Invoke read -> ubpir方式
//2.在调用时多了三个步骤
// 2.1-需要先压入ref或out参数的初始值
// 2.2-压入参数环节压入引用索引值
// 2.3-通过Read按顺序获取ref、out参数,返回值最后获取
#endregion
}
}
9.3 练习题
练习一下Unity跨域调用ILRuntime中的带有ref/out参数的方法
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com