9.Unity调用ILR对象ref和out方法

9.Unity调用ILRuntime-方法调用-ref和out方法调用


9.1 知识点

ref/out方法调用

ref/out方法调用概述

需要通过 IMethod 方法调用,并且需要使用无GC Alloc方法调用。

  1. 和其他函数不一样的地方是需要先压入 refout 参数的初始值。

  2. 和其他函数调用写法一致,需要压入调用对象和各参数。

  3. refout 参数因为在一开始就压入了值,在这里需要压入它们的索引位置。refout 参数压入参数引用索引值即可,从0开始。

  4. 通过 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
    }
});

总结

  1. ref/out方法只能通过无GC Alloc方法调用 using BeginInvokepushinvokereadubpir方式。

  2. 在调用时多了三个步骤:

    • 需要先压入 refout 参数的初始值。
    • 压入参数环节压入引用索引值。
    • 通过 Read 按顺序获取 refout 参数,返回值最后获取。

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

×

喜欢就点赞,疼爱就打赏