c#语言是如何和lua语言进行通信的

C#和Lua之间的通信通常通过嵌入Lua解释器到C#应用程序中来实现。最常用的库是NLuaMoonSharp。NLua是基于LuaInterface的一个库,而MoonSharp是一个完全用C#编写的Lua解释器。下面我们将介绍如何使用这两个库来实现C#和Lua的通信。

使用NLua

NLua是一个流行的库,用于在C#中嵌入Lua。以下是一个简单的示例,展示如何在C#中使用NLua与Lua进行通信。

安装NLua

首先,你需要在你的C#项目中安装NLua。你可以使用NuGet包管理器来安装:

Install-Package NLua
示例代码

以下是一个简单的示例,展示如何在C#中使用NLua执行Lua脚本,并进行数据交换。

using System;
using NLua;

class Program
{
    static void Main()
    {
        // 创建一个Lua解释器实例
        using (Lua lua = new Lua())
        {
            // 执行一个简单的Lua脚本
            lua.DoString(@"
                function add(a, b)
                    return a + b
                end
            ");

            // 调用Lua函数
            LuaFunction addFunction = lua["add"] as LuaFunction;
            object[] result = addFunction.Call(3, 4);
            Console.WriteLine("Result of add(3, 4): " + result[0]);

            // 传递C#变量到Lua
            lua["x"] = 10;
            lua["y"] = 20;
            lua.DoString("z = x + y");
            Console.WriteLine("Result of x + y: " + lua["z"]);
        }
    }
}

使用MoonSharp

MoonSharp是另一个流行的库,它是一个完全用C#编写的Lua解释器。以下是一个简单的示例,展示如何在C#中使用MoonSharp与Lua进行通信。

安装MoonSharp

首先,你需要在你的C#项目中安装MoonSharp。你可以使用NuGet包管理器来安装:

Install-Package MoonSharp
示例代码

以下是一个简单的示例,展示如何在C#中使用MoonSharp执行Lua脚本,并进行数据交换。

using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        // 初始化MoonSharp
        Script script = new Script();

        // 执行一个简单的Lua脚本
        script.DoString(@"
            function add(a, b)
                return a + b
            end
        ");

        // 调用Lua函数
        DynValue addFunction = script.Globals.Get("add");
        DynValue result = script.Call(addFunction, 3, 4);
        Console.WriteLine("Result of add(3, 4): " + result.Number);

        // 传递C#变量到Lua
        script.Globals["x"] = 10;
        script.Globals["y"] = 20;
        script.DoString("z = x + y");
        Console.WriteLine("Result of x + y: " + script.Globals.Get("z").Number);
    }
}

总结

通过使用NLua或MoonSharp库,你可以在C#中嵌入Lua解释器,实现C#和Lua之间的通信。这两个库都提供了丰富的API,支持执行Lua脚本、调用Lua函数、传递变量等功能。选择哪个库取决于你的具体需求和偏好。NLua基于原生Lua解释器,性能较高,但需要依赖原生库;MoonSharp完全用C#编写,易于集成,但性能可能稍逊于NLua。

好的,让我们继续深入探讨C#和Lua之间的通信,进一步扩展和深入理解如何在实际项目中应用这些技术。

高级用法和最佳实践

1. 调用Lua函数并处理返回值

在实际项目中,你可能需要调用Lua函数并处理其返回值。以下是一个示例,展示如何在C#中调用Lua函数并处理多种类型的返回值。

使用NLua
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            lua.DoString(@"
                function processData(a, b)
                    return a + b, a * b, a / b
                end
            ");

            LuaFunction processData = lua["processData"] as LuaFunction;
            object[] result = processData.Call(10, 5);

            Console.WriteLine("Sum: " + result[0]);
            Console.WriteLine("Product: " + result[1]);
            Console.WriteLine("Division: " + result[2]);
        }
    }
}
使用MoonSharp
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        script.DoString(@"
            function processData(a, b)
                return a + b, a * b, a / b
            end
        ");

        DynValue processData = script.Globals.Get("processData");
        DynValue result = script.Call(processData, 10, 5);

        Console.WriteLine("Sum: " + result.Tuple[0].Number);
        Console.WriteLine("Product: " + result.Tuple[1].Number);
        Console.WriteLine("Division: " + result.Tuple[2].Number);
    }
}
2. 从C#调用Lua脚本中的类和对象

在Lua脚本中定义类和对象,并在C#中调用它们,可以实现更复杂的逻辑和数据结构。

使用NLua
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            lua.DoString(@"
                Person = {}
                Person.__index = Person

                function Person:new(name, age)
                    local self = setmetatable({}, Person)
                    self.name = name
                    self.age = age
                    return self
                end

                function Person:greet()
                    return 'Hello, my name is ' .. self.name .. ' and I am ' .. self.age .. ' years old.'
                end
            ");

            LuaFunction newPerson = lua["Person.new"] as LuaFunction;
            object person = newPerson.Call(lua["Person"], "John", 30)[0];

            LuaFunction greet = lua["Person.greet"] as LuaFunction;
            string greeting = greet.Call(person)[0] as string;

            Console.WriteLine(greeting);
        }
    }
}
使用MoonSharp
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        script.DoString(@"
            Person = {}
            Person.__index = Person

            function Person:new(name, age)
                local self = setmetatable({}, Person)
                self.name = name
                self.age = age
                return self
            end

            function Person:greet()
                return 'Hello, my name is ' .. self.name .. ' and I am ' .. self.age .. ' years old.'
            end
        ");

        DynValue newPerson = script.Globals.Get("Person").Table.Get("new");
        DynValue person = script.Call(newPerson, script.Globals.Get("Person"), "John", 30);

        DynValue greet = person.Table.Get("greet");
        string greeting = script.Call(greet, person).String;

        Console.WriteLine(greeting);
    }
}
3. 在C#中注册函数供Lua调用

有时你需要在C#中定义函数,并将其注册到Lua中,以便Lua脚本可以调用这些函数。

使用NLua
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            lua.RegisterFunction("printMessage", null, typeof(Program).GetMethod("PrintMessage"));

            lua.DoString(@"
                printMessage('Hello from Lua!')
            ");
        }
    }

    public static void PrintMessage(string message)
    {
        Console.WriteLine(message);
    }
}

好的,让我们继续深入探讨如何在C#中注册函数供Lua调用,并进一步扩展一些高级用法和最佳实践。

在C#中注册函数供Lua调用

使用MoonSharp

MoonSharp提供了一个简单的方法来注册C#函数,使其可以在Lua脚本中调用。以下是一个示例,展示如何在C#中注册函数并在Lua中调用它。

using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        // 初始化MoonSharp
        Script script = new Script();

        // 注册C#函数到Lua
        script.Globals["printMessage"] = (Action<string>)PrintMessage;

        // 执行Lua脚本调用C#函数
        script.DoString(@"
            printMessage('Hello from Lua!')
        ");
    }

    public static void PrintMessage(string message)
    {
        Console.WriteLine(message);
    }
}

4. 在Lua中定义类并在C#中实例化和调用

在Lua中定义类,并在C#中实例化这些类并调用其方法,可以实现更复杂的逻辑和数据结构。

使用NLua
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            lua.DoString(@"
                Person = {}
                Person.__index = Person

                function Person:new(name, age)
                    local self = setmetatable({}, Person)
                    self.name = name
                    self.age = age
                    return self
                end

                function Person:greet()
                    return 'Hello, my name is ' .. self.name .. ' and I am ' .. self.age .. ' years old.'
                end
            ");

            LuaFunction newPerson = lua["Person.new"] as LuaFunction;
            object person = newPerson.Call(lua["Person"], "John", 30)[0];

            LuaFunction greet = lua["Person.greet"] as LuaFunction;
            string greeting = greet.Call(person)[0] as string;

            Console.WriteLine(greeting);
        }
    }
}
使用MoonSharp
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        script.DoString(@"
            Person = {}
            Person.__index = Person

            function Person:new(name, age)
                local self = setmetatable({}, Person)
                self.name = name
                self.age = age
                return self
            end

            function Person:greet()
                return 'Hello, my name is ' .. self.name .. ' and I am ' .. self.age .. ' years old.'
            end
        ");

        DynValue newPerson = script.Globals.Get("Person").Table.Get("new");
        DynValue person = script.Call(newPerson, script.Globals.Get("Person"), "John", 30);

        DynValue greet = person.Table.Get("greet");
        string greeting = script.Call(greet, person).String;

        Console.WriteLine(greeting);
    }
}

好的,让我们继续深入探讨如何在C#中处理Lua的错误和异常,并进一步扩展一些高级用法和最佳实践。

在C#中处理Lua的错误和异常(续)

使用MoonSharp(续)
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        script.DoString(@"
            function divide(a, b)
                if b == 0 then
                    error('Division by zero!')
                end
                return a / b
            end
        ");

        try
        {
            DynValue divide = script.Globals.Get("divide");
            DynValue result = script.Call(divide, 10, 0);
            Console.WriteLine("Result: " + result.Number);
        }
        catch (ScriptRuntimeException ex)
        {
            Console.WriteLine("Lua Error: " + ex.DecoratedMessage);
        }
    }
}

6. 在C#中调用Lua的协程

Lua的协程(coroutine)是一个强大的特性,可以实现协作式多任务处理。以下是如何在C#中调用Lua的协程。

使用NLua
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            lua.DoString(@"
                function countToTen()
                    for i = 1, 10 do
                        coroutine.yield(i)
                    end
                end
            ");

            LuaFunction countToTen = lua["countToTen"] as LuaFunction;
            LuaThread thread = lua.CreateThread(countToTen);

            while (true)
            {
                var result = thread.Resume();
                if (result[0] is bool && !(bool)result[0])
                {
                    break;
                }
                Console.WriteLine("Count: " + result[1]);
            }
        }
    }
}
使用MoonSharp
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        script.DoString(@"
            function countToTen()
                for i = 1, 10 do
                    coroutine.yield(i)
                end
            end
        ");

        DynValue coroutine = script.CreateCoroutine(script.Globals.Get("countToTen"));

        while (true)
        {
            DynValue result = coroutine.Coroutine.Resume();
            if (result.Type == DataType.Tuple && result.Tuple.Length > 0 && result.Tuple[0].Type == DataType.Nil)
            {
                break;
            }
            Console.WriteLine("Count: " + result.Tuple[0].Number);
        }
    }
}

7. 在C#中与Lua表进行交互

Lua表是Lua中最重要的数据结构之一。以下是如何在C#中与Lua表进行交互。

使用NLua
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            lua.DoString(@"
                myTable = { name = 'John', age = 30 }
            ");

            LuaTable myTable = lua["myTable"] as LuaTable;
            string name = myTable["name"] as string;
            double age = (double)myTable["age"];

            Console.WriteLine("Name: " + name);
            Console.WriteLine("Age: " + age);

            myTable["age"] = 31;
            Console.WriteLine("Updated Age: " + myTable["age"]);
        }
    }
}
使用MoonSharp
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        script.DoString(@"
            myTable = { name = 'John', age = 30 }
        ");

        Table myTable = script.Globals.Get("myTable").Table;
        string name = myTable.Get("name").String;
        double age = myTable.Get("age").Number;

        Console.WriteLine("Name: " + name);
        Console.WriteLine("Age: " + age);

        myTable.Set("age", DynValue.NewNumber(31));
        Console.WriteLine("Updated Age: " + myTable.Get("age").Number);
    }
}

好的,让我们继续探讨如何在C#中与Lua元表进行交互,并进一步扩展一些高级用法和最佳实践。

在C#中与Lua元表进行交互

Lua元表(metatable)是一个强大的特性,可以用来改变表的行为。以下是如何在C#中与Lua元表进行交互。

使用NLua
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            lua.DoString(@"
                myTable = { x = 10, y = 20 }
                myMetatable = {
                    __index = function(table, key)
                        if key == 'z' then
                            return table.x + table.y
                        end
                    end
                }
                setmetatable(myTable, myMetatable)
            ");

            LuaTable myTable = lua["myTable"] as LuaTable;
            LuaTable myMetatable = lua["myMetatable"] as LuaTable;

            double x = (double)myTable["x"];
            double y = (double)myTable["y"];
            double z = (double)myTable["z"];

            Console.WriteLine("x: " + x);
            Console.WriteLine("y: " + y);
            Console.WriteLine("z: " + z);
        }
    }
}
使用MoonSharp
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        script.DoString(@"
            myTable = { x = 10, y = 20 }
            myMetatable = {
                __index = function(table, key)
                    if key == 'z' then
                        return table.x + table.y
                    end
                end
            }
            setmetatable(myTable, myMetatable)
        ");

        Table myTable = script.Globals.Get("myTable").Table;
        Table myMetatable = script.Globals.Get("myMetatable").Table;

        double x = myTable.Get("x").Number;
        double y = myTable.Get("y").Number;
        double z = myTable.Get("z").Number;

        Console.WriteLine("x: " + x);
        Console.WriteLine("y: " + y);
        Console.WriteLine("z: " + z);
    }
}

9. 在C#中与Lua的模块和包进行交互

Lua的模块和包系统允许你组织和重用代码。以下是如何在C#中与Lua的模块和包进行交互。

使用NLua
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            lua.DoString(@"
                myModule = {}
                function myModule.greet(name)
                    return 'Hello, ' .. name
                end
                return myModule
            ");

            LuaTable myModule = lua["myModule"] as LuaTable;
            LuaFunction greet = myModule["greet"] as LuaFunction;

            string greeting = greet.Call("John")[0] as string;
            Console.WriteLine(greeting);
        }
    }
}
使用MoonSharp
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        script.DoString(@"
            myModule = {}
            function myModule.greet(name)
                return 'Hello, ' .. name
            end
            return myModule
        ");

        Table myModule = script.Globals.Get("myModule").Table;
        DynValue greet = myModule.Get("greet");

        string greeting = script.Call(greet, "John").String;
        Console.WriteLine(greeting);
    }
}

好的,让我们继续探讨如何在C#中与Lua的环境进行交互,并进一步扩展一些高级用法和最佳实践。

在C#中与Lua的环境进行交互(续)

使用NLua(续)
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            lua.DoString(@"
                myEnv = { x = 10, y = 20 }
                setfenv(1, myEnv)
            ");

            LuaTable myEnv = lua["myEnv"] as LuaTable;

            double x = (double)myEnv["x"];
            double y = (double)myEnv["y"];

            Console.WriteLine("x: " + x);
            Console.WriteLine("y: " + y);

            // 修改环境中的变量
            myEnv["x"] = 30;
            myEnv["y"] = 40;

            Console.WriteLine("Updated x: " + myEnv["x"]);
            Console.WriteLine("Updated y: " + myEnv["y"]);
        }
    }
}
使用MoonSharp
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        script.DoString(@"
            myEnv = { x = 10, y = 20 }
            setfenv(1, myEnv)
        ");

        Table myEnv = script.Globals.Get("myEnv").Table;

        double x = myEnv.Get("x").Number;
        double y = myEnv.Get("y").Number;

        Console.WriteLine("x: " + x);
        Console.WriteLine("y: " + y);

        // 修改环境中的变量
        myEnv.Set("x", DynValue.NewNumber(30));
        myEnv.Set("y", DynValue.NewNumber(40));

        Console.WriteLine("Updated x: " + myEnv.Get("x").Number);
        Console.WriteLine("Updated y: " + myEnv.Get("y").Number);
    }
}

好的,让我们继续探讨如何在C#中与Lua的元方法进行交互,并进一步扩展一些高级用法和最佳实践。

在C#中与Lua的元方法进行交互(续)

使用MoonSharp(续)
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        script.DoString(@"
            myTable = { x = 10, y = 20 }
            myMetatable = {
                __add = function(a, b)
                    return { x = a.x + b.x, y = a.y + b.y }
                end
            }
            setmetatable(myTable, myMetatable)
        ");

        Table myTable = script.Globals.Get("myTable").Table;
        Table myMetatable = script.Globals.Get("myMetatable").Table;

        script.Globals.Set("otherTable", DynValue.NewTable(script));
        Table otherTable = script.Globals.Get("otherTable").Table;
        otherTable.Set("x", DynValue.NewNumber(5));
        otherTable.Set("y", DynValue.NewNumber(15));

        DynValue result = script.DoString("return myTable + otherTable");
        Table resultTable = result.Table;

        double x = resultTable.Get("x").Number;
        double y = resultTable.Get("y").Number;

        Console.WriteLine("x: " + x);
        Console.WriteLine("y: " + y);
    }
}

12. 在C#中与Lua的用户数据进行交互

用户数据(userdata)是Lua中一种特殊的数据类型,用于表示C#对象。以下是如何在C#中与Lua的用户数据进行交互。

使用NLua
using System;
using NLua;

class MyClass
{
    public int Value { get; set; }

    public MyClass(int value)
    {
        Value = value;
    }

    public void PrintValue()
    {
        Console.WriteLine("Value: " + Value);
    }
}

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            MyClass myObject = new MyClass(42);
            lua["myObject"] = myObject;

            lua.DoString(@"
                print('Value from Lua: ' .. myObject.Value)
                myObject:PrintValue()
            ");
        }
    }
}
使用MoonSharp
using System;
using MoonSharp.Interpreter;

[MoonSharpUserData]
class MyClass
{
    public int Value { get; set; }

    public MyClass(int value)
    {
        Value = value;
    }

    public void PrintValue()
    {
        Console.WriteLine("Value: " + Value);
    }
}

class Program
{
    static void Main()
    {
        UserData.RegisterType<MyClass>();

        Script script = new Script();
        MyClass myObject = new MyClass(42);
        script.Globals["myObject"] = myObject;

        script.DoString(@"
            print('Value from Lua: ' .. myObject.Value)
            myObject:PrintValue()
        ");
    }
}

13. 在C#中与Lua的调试和日志进行交互

调试和日志记录是开发过程中非常重要的部分。以下是如何在C#中与Lua的调试和日志进行交互。

使用NLua
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            lua.HookException += (sender, e) =>
            {
                Console.WriteLine("Lua Exception: " + e.Exception.Message);
            };

            lua.DoString(@"
                function faultyFunction()
                    error('This is an error!')
                end

                faultyFunction()
            ");
        }
    }
}
使用MoonSharp
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        script.Options.DebugPrint = s => Console.WriteLine("Lua Debug: " + s);

        try
        {
            script.DoString(@"
                function faultyFunction()
                    error('This is an error!')
                end

                faultyFunction()
            ");
        }
        catch (ScriptRuntimeException ex)
        {
            Console.WriteLine("Lua Exception: " + ex.DecoratedMessage);
        }
    }
}

好的,让我们继续探讨在C#中与Lua进行性能优化的策略和最佳实践。

在C#中与Lua的性能优化

性能优化是开发过程中不可忽视的一部分。以下是一些在C#中与Lua进行性能优化的策略和最佳实践。

1. 减少跨语言调用

跨语言调用(从C#调用Lua,或从Lua调用C#)的开销较大,尽量减少不必要的跨语言调用。

2. 缓存Lua函数和表

如果需要频繁调用Lua函数或访问Lua表,建议将它们缓存到C#变量中,以减少查找开销。

使用NLua
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            lua.DoString(@"
                function add(a, b)
                    return a + b
                end
            ");

            LuaFunction addFunction = lua["add"] as LuaFunction;

            for (int i = 0; i < 1000000; i++)
            {
                double result = (double)addFunction.Call(1, 2)[0];
            }
        }
    }
}
使用MoonSharp
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        script.DoString(@"
            function add(a, b)
                return a + b
            end
        ");

        DynValue addFunction = script.Globals.Get("add");

        for (int i = 0; i < 1000000; i++)
        {
            double result = script.Call(addFunction, 1, 2).Number;
        }
    }
}
3. 预编译Lua脚本

预编译Lua脚本可以减少运行时的编译开销。

使用NLua
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            LuaFunction compiledScript = lua.LoadString(@"
                function add(a, b)
                    return a + b
                end
            ");

            compiledScript.Call();

            LuaFunction addFunction = lua["add"] as LuaFunction;

            for (int i = 0; i < 1000000; i++)
            {
                double result = (double)addFunction.Call(1, 2)[0];
            }
        }
    }
}
使用MoonSharp
using System;
using MoonSharp.Interpreter;

class Program
{
    static void Main()
    {
        Script script = new Script();

        DynValue compiledScript = script.LoadString(@"
            function add(a, b)
                return a + b
            end
        ");

        compiledScript.Function.Call();

        DynValue addFunction = script.Globals.Get("add");

        for (int i = 0; i < 1000000; i++)
        {
            double result = script.Call(addFunction, 1, 2).Number;
        }
    }
}
4. 使用LuaJIT

LuaJIT(Just-In-Time Compiler for Lua)可以显著提高Lua脚本的执行速度。NLua和MoonSharp不直接支持LuaJIT,但你可以使用其他库或工具来集成LuaJIT。

15. 在C#中与Lua的错误处理

错误处理是开发过程中不可忽视的一部分。以下是如何在C#中与Lua的错误处理进行交互。

使用NLua
using System;
using NLua;

class Program
{
    static void Main()
    {
        using (Lua lua = new Lua())
        {
            lua.HookException += (sender, e) =>
            {
                Console.WriteLine("Lua Exception: " + e.Exception.Message);
            };

            try
            {
                lua.DoString(@"
                    function faultyFunction()
                        error('This is an error!')
                    end

                    faultyFunction()
                ");
            }
            catch (LuaException ex)
            {
                Console.WriteLine("Caught Lua Exception: " + ex.Message);
            }
        }
    }
}
  • 16
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牛掰是怎么形成的

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值