XLua_API

合集下载

xlua重复利用协程函数

xlua重复利用协程函数

xlua重复利用协程函数如何在Lua编程语言中使用协程函数实现重复利用功能?协程函数是一种可以被挂起和恢复的特殊函数。

在Lua中,我们可以使用xlua库来实现协程功能。

协程函数可以让我们在代码执行的不同点之间切换,以此实现重复利用的功能。

在本文中,我们将探讨如何使用xlua库来实现重复利用协程函数。

我们将按照以下步骤进行:第一步:安装xlua库在开始之前,我们需要先安装xlua库。

可以在Lua的官方网站上找到相关的安装包和文档。

第二步:导入xlua库在我们的代码中,首先需要导入xlua库。

可以使用require函数来导入。

lualocal xlua = require("xlua")第三步:定义协程函数我们需要定义一个协程函数,用于实现重复利用的功能。

协程函数是一个普通的Lua函数,但是在函数内部可以使用一些特殊的函数来控制协程的执行流程。

在本文中,我们将定义一个名为repeatCoroutine的协程函数,它会重复执行一些代码块。

我们使用了xlua库提供的特殊函数coroutine.yield来实现协程的暂停和恢复。

lualocal function repeatCoroutine()while true doprint("Hello, World!")xlua.coroutine.yield()endend在上面的代码中,我们使用了一个无限循环来表示代码块的重复执行。

在每次循环中,我们打印了"Hello, World!"并使用xlua.coroutine.yield函数来暂停协程的执行。

第四步:创建协程对象在我们的代码中,我们需要创建一个协程对象,以便在需要的时候启动协程执行。

lualocal repeatCoroutineObj = xlua.coroutine.create(repeatCoroutine)在上面的代码中,我们使用xlua.coroutine.create函数来创建一个协程对象。

LuaPerfect使用说明

LuaPerfect使用说明

欢迎使用Lua Perfect一、欢迎欢迎您使用LuaPerfect!LuaPerfect是TX开发的专业级的Lua调试器,致力于为广大Lua开发人员提供免费的专业的Lua调试工具。

二、调试指南1、LuaPerfect调试原理如下图所示,LuaPerfect的调试原理是通过在游戏中通过require("LuaDebuggee")来加载LuaDebuggee.dll,并通过LuaDebugee模块设置调试钩子,从而完成调试的功能。

图1、LuaPerfect调试原理2、LuaPerfect调试具体步骤步骤1:在LuaPerfect工程列表里选择需要打开的项目,打开项目的同时,LuaPerfect会自动地将LuaDebuggee复制到工程的目录,以供游戏中调用(无需手动复制)。

步骤2:在工程入口点的Lua文件的开头,粘贴如下代码:require('LuaDebuggee').StartDebug("127.0.0.1",9826)步骤3:在刚刚添加的语句后面执行的语句处放置一个断点(快捷键F9)。

在Unity里启动游戏,即会断点到该断点处。

特别说明1:由于XLua官方示例工程中很多地方使用DoString(),建议使用自带的00_LuaPerfectTest_XLua这个例子进行测试,自带的例子在官方群00_LuaPerfectTest_XLua.zip 中。

特别说明2:如果加入require(“LuaDebuggee”).StartDebug(“127.0.0.1”,9826)后,自定义的CustomLuaLoader里发生错误,提示找不到LuaDebuggee.lua或者类似的提示。

请修改CustomLuaLoader,对于”LuaDebuggee”的情况,直接返回0。

public static int MyCustomLoader(IntPtr L){string libararyName=XLua.LuaDLL.Lua.lua_tostring(L,1);if(libararyName=="LuaDebuggee")//加上这个判断"LuaDebuggee"返回0的即可调试{return0;}...其他代码}图2、成功启动调试三、直接查看Unity对象成员LuaPerfect除了提供查看常规的Lua值/对象的能力,也提供了查看Unity里的C#对象成员的能力,并且更进一步,如果查看的对象是GameObject对象,会列出其各个子GameObject 对象及GameComponent对象。

利用阿里云的API实现动态域名解析

利用阿里云的API实现动态域名解析

利用阿里云的API实现动态域名解析首先在实现动态域名解析之前要具备两个条件:第一、你必须有公网 IP,就是你的路由器拨号获取到的 IP 必须是公网 IP (可以参考 ip138 获取到的 IP)。

长城宽带没有公公网 IP 所以就不用往下看了,用内网穿透的工具吧,那天在家搭服务器时发现联通给的也是内网IP,果断投诉他们,让他们换成公网的 IP。

第二、你必须有阿里云的域名,API 是阿里云提供的,阿里云提供域名解析,所以没有域名就没法解析了。

进入正题,先说一下原理:一个 windows 服务,定时获取公网 IP ,然后调用 API 接口设置解析。

首先从阿里云上把 SDK 下载下来,源码需要自己编译,这里我们只用到了 core 和 alidns 两个项目,一个是核心组件,一个是 dns 接口组件。

其实我只用到了 3 个接口:•DescribeDomainRecords 获取域名的解析列表•AddDomainRecord 添加一条新的解析记录•UpdateDomainRecord 修改一条解析记录获取域名的解析列表CGlobalConfig.AccessKey 是获取配置文件里配置的阿里云的AccessKey,这个需要去阿里云申请(不花钱)。

CGlobalConfig.AccessKeySecret 是获取配置文件里配置的阿里云的 AccessKeySecret,这个跟 AccessKey 是一对。

domain 变量是域名1.IClientProfile clientProfile = DefaultProfile.GetProfile("cn-hangzhou", CGlobalConfig.AccessKey, CGlobalConfig.AccessKeySecret);2.DefaultAcsClient client = new DefaultAcsClient(clientProfile);3.DescribeDomainRecordsRequest request = new DescribeDomainRecordsRequest();4.request.DomainName = domain;5.DescribeDomainRecordsResponse response = client.GetAcsResponse(request);6.List<DescribeDomainRecordsResponse.Record> list = response.DomainRecords;获取到的 list 就是这个域名的解析记录。

关于XLua与C#之间的通信分析

关于XLua与C#之间的通信分析

关于XLua与C#之间的通信分析分析了一下XLua与C#之间的通信方式,发现和SLua,Ulua的区别不是很大。

Lua调用C#:都是需要先生成一个个wrap文件,C#才能被lua调用。

wrap文件相当于一个接口,Lua先调用wrap文件然后wrap 再调用C#,在wrap 文件里面实际上是把C#的类函数,字段压入到lua虚拟机的虚拟栈上,再由lua虚拟机出栈后给lua调用的。

当索引系统API、dll库或者第三方库时,无法将代码的具体实现进行代码生成,采用C#的反射方式实现交互,缺点是执行效率低。

也就是说Lua调用C#其实就是:lua->wrap->C#那么在XLua中C#又是如何调用Lua的呢?看源码很容易知道,其实是使用如下函数:LuaEnv luaenv = new LuaEnv();//创建Lua虚拟机luaenv.DoString("CS.UnityEngine.Debug.Log('hello world')");执行lua代码根据XLua的文档,DoString可以直接执行字符串代码,也可以加载lua文件执行,分析源码发现DoString其实是调用的外部DLL中的xluaL_loadbuffer函数,如下DoString 定义:public object[] DoString(byte[] chunk, string chunkName = "chunk", LuaTable env = null){#if THREAD_SAFE || HOTFIX_ENABLElock (luaEnvLock){#endifvar _L = L;int oldTop = LuaAPI.lua_gettop(_L);int errFunc = LuaAPI.load_error_func(_L, errorFuncRef);if (LuaAPI.xluaL_loadbuffer(_L, chunk, chunk.Length, chunkName) == 0){if (env != null){env.push(_L);LuaAPI.lua_setfenv(_L, -2);}if (LuaAPI.lua_pcall(_L, 0, -1, errFunc) == 0){LuaAPI.lua_remove(_L, errFunc);return translator.popValues(_L, oldTop);}elseThrowExceptionFromError(oldTop);}elseThrowExceptionFromError(oldTop);return null;#if THREAD_SAFE || HOTFIX_ENABLE}而xluaL_loadbuffer 外部引入声明如下:[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]public static extern int xluaL_loadbuffer(IntPtr L, byte[] buff, int size, string name);也就说xluaL_loadbuffer的函数实现并不在源文件中,而是在外部DLL文件中实现的。

xlua framework 基础用法

xlua framework 基础用法

xlua framework 基础用法xlua framework 是一种面向游戏开发的 Lua 扩展框架,它提供了一些额外的功能和优化,以提高 Lua 在游戏开发中的性能和灵活性。

基本用法如下所示:1. 导入 xlua 框架:```luarequire("xlua")```2. 定义一个类:```lualocal MyClass = {}MyClass.__index = MyClassfunction MyClass.new()local self = setmetatable({}, MyClass)return selfendfunction MyClass:MyMethod()print("Hello from MyClass!")end```3. 创建对象并调用方法:```lualocal myObject = MyClass.new()myObject:MyMethod()```4. 继承和重写方法:```lualocal DerivedClass = {}setmetatable(DerivedClass, { __index = MyClass }) DerivedClass.__index = DerivedClassfunction DerivedClass.new()local self = setmetatable({}, DerivedClass)return selfendfunction DerivedClass:MyMethod()print("Hello from DerivedClass!")end```5. 调用基类方法:```lualocal derivedObject = DerivedClass.new()derivedObject:MyMethod() -- 输出 "Hello from DerivedClass!" getmetatable(derivedObject).__index.MyMethod(derivedObject) -- 输出 "Hello from MyClass!"```这仅仅是 xlua framework 的基础用法,该框架还提供了很多其他的功能和工具,如自动绑定 C# 类、导出 Unity3D 引擎的接口等,你可以根据具体需求来进一步学习和使用。

腾讯开源手游热更新方案,Unity3D下的Lua编程

腾讯开源手游热更新方案,Unity3D下的Lua编程

腾讯开源⼿游热更新⽅案,Unity3D下的Lua编程作者|车雄⽣编辑|⽊环腾讯最近在开源⽅⾯的动作不断:先是微信跨平台基础组件Mars宣布开源,腾讯⼿游⼜于近期开源了Unity3D下Lua编程解决⽅案——xLua。

xLua,何⽅神圣?有哪些技术细节可以说道说道?写在前⾯xLua是Unity3D下Lua编程解决⽅案,⾃2016年初推⼴以来,已经应⽤于⼗多款腾讯⾃研游戏,因其良好性能、易⽤性、扩展性⽽⼴受好评。

现在腾讯已经将xLua开源到GitHub。

2016年12⽉末,xLua刚刚实现新的突破:全平台⽀持⽤Lua修复C#代码bug。

⽬前Unity下的Lua热更新⽅案⼤多都是要求要热更新的部分⼀开始就要⽤Lua语⾔实现,不⾜之处在于:1. 接⼊成本⾼,有的项⽬已经⽤C#写完了,这时要接⼊需要把需要热更的地⽅⽤Lua重新实现;2. 即使⼀开始就接⼊了,也存在同时⽤两种语⾔开发难度较⼤的问题;3. Lua性能不如C#;xLua热补丁技术⽀持在运⾏时把⼀个C#实现(函数,操作符,属性,事件,或者整个类)替换成Lua实现,意味着你可以:1. 平时⽤C#开发;2. 运⾏也是C#,性能秒杀Lua;3. 有bug的地⽅下发个Lua脚本fix了,下次整体更新时可以把Lua的实现换回正确的C#实现,更新时甚⾄可以做到不重启游戏;这个新特性iOS,Android,Windows,Mac都测试通过了,⽬前在做⼀些易⽤性优化。

那么,腾讯开源的xLua究竟是怎样的技术?它是为何如此设计的?更令⼈关⼼的是,xLua的性能如何?带着这些问题,InfoQ对其作者进⾏了采访并将内容整理成⽂。

技术背景腾讯⾃研⼿游,就我了解的项⽬来说,⼤多数游戏引擎都是Unity3D,少数⽤coco2d。

xLua这个插件具体⽤到了哪些游戏中?虽说xLua是2015年3⽉就完成了第⼀个版本,但由于当时项⽬组热更的意识并没有很普遍,需求不是很强烈,xLua的开发资源都调到更紧急的项⽬了。

深入理解xLua热更新原理

深入理解xLua热更新原理

深⼊理解xLua热更新原理热更新简介热更新是指在不需要重新编译打包游戏的情况下,在线更新游戏中的⼀些⾮核⼼代码和资源,⽐如活动运营和打补丁。

热更新分为资源热更新和代码热更新两种,代码热更新实际上也是把代码当成资源的⼀种热更新,但通常所说的热更新⼀般是指代码热更新。

资源热更新主要通过AssetBundle来实现,在Unity编辑器内为游戏中所⽤到的资源指定AB包的名称和后缀,然后进⾏打包并上传服务器,待游戏运⾏时动态加载服务器上的AB资源包。

代码热更新主要包括Lua热更新、ILRuntime热更新和C#直接反射热更新等。

由于ILRuntime热更新还不成熟可能存在⼀些坑,⽽C#直接反射热更新⼜不⽀持IOS平台,因此⽬前⼤多采⽤更成熟的、没有平台限制的Lua热更新⽅案。

为什么需要热更新⼀般情况下,游戏开发并测试完后就要提交应⽤商店审核,其中苹果商店审核周期最长,审核通过后才能上线发布,这时玩家才能下载安装游戏。

在如今快节奏的⼿游时代,游戏的⽣命周期⼤幅缩短⽽且更新还很频繁,如果每次游戏更新都要重新编译游戏打包,然后等待审核发布,最后⽤户再下载安装游戏,那玩家的耐性早没了。

⽽且游戏安装包还不能太⼤,不然玩家还没等到游戏下载安装好就失去兴趣了。

正确的⽅式是将游戏中⼀些⾮核⼼的资源打包并上传服务器,等游戏下载安装好实际运⾏时才在线动态加载资源,从⽽减少游戏安装包的⼤⼩。

因此,我们急需⼀种不需要重新编译打包就能在线更新游戏中的⼀些⾮核⼼代码和资源,⽽这种⽅式就是热更新。

热更新分为资源热更新和代码热更新,资源热更新主要是指将游戏中⼀些资源打包成AB包,并上传服务器,等游戏运⾏时才从服务器上加载资源。

通过这种⽅式可以减少游戏安装包的⼤⼩,减少⽤户下载游戏的时间。

其次,可以通过这种⽅式动态加载游戏中的资源,⽐如节假⽇有活动运营时,可以直接在线更新游戏中的场景,不需要重新发布游戏和重新下载安装游戏,进⽽提⾼玩家的游戏体验。

Unity使用xLua遇到的坑

Unity使用xLua遇到的坑

Unity使⽤xLua遇到的坑在我们使⽤xLua作为Unity中lua集成的解决⽅案时,遇到了⼀个问题,就是当我们使⽤在lua中把UI中的某个控件绑定相应的事件(如按钮的onClick事件),xLua绑定这个事件是⽤委托实现的,具体代码可以查看xLua的代码。

⽽在程序退出的时候xLua会检查对应的委托有没有被正确的释放掉,如果没有释放掉的话就会抛出异常。

代码如表所⽰:1public virtual void Dispose(bool dispose)2 {3#if THREAD_SAFE || HOTFIX_ENABLE4lock (luaEnvLock)5 {6#endif7if (disposed) return;8 Tick();910if (!translator.AllDelegateBridgeReleased())11 {12throw new InvalidOperationException("try to dispose a LuaEnv with C# callback!");13 }1415 LuaAPI.lua_close(L);1617 ObjectTranslatorPool.Instance.Remove(L);18 translator = null;1920 rawL = IntPtr.Zero;2122 disposed = true;23#if THREAD_SAFE || HOTFIX_ENABLE24 }25#endif26 }这说明我们并没有把对应的委托给释放掉。

所以我们需要确保在程序退出之前所有的委托要正确地释放掉。

⽅案⼤体如下,每⼀个UI都对应⼀个实例,这样在绑定控件的时候创建⼀个匿名函数,这个函数⽤于控件把这个控件绑定的事件清除掉,同时把这个匿名函数放到⼀个数组⾥⾯去,在这个UI销毁的时候调⽤⼀个函数(⽐如我们叫做Destroy),这个函数的作⽤就是负责⼀些清理⼯作,其中就包括遍历前⾯提到的匿名函数的数组并挨个调⽤。

xlua原理

xlua原理

xlua原理
XLua是一种用于在Unity游戏引擎中集成Lua脚本的插件。

它提供了一种将Lua脚本与Unity游戏进行交互的方式,使开发人员可以通过编写Lua脚本来扩展和定制游戏逻辑。

XLua的原理可以简要概括如下:
1. 绑定C#代码:XLua通过将C#代码绑定到Lua环境中,使Lua脚本能够访问和调用C#的函数和属性。

通过使用反射技术和元表机制,XLua可以将C#代码转换为Lua可以理解和调用的形式。

2. Lua虚拟机:XLua使用Lua虚拟机来执行Lua脚本。

Lua虚拟机是一个解释器,可以加载和执行Lua脚本。

XLua 在Unity启动时创建Lua虚拟机实例,并将其与C#环境进行绑定。

3. 脚本加载和执行:XLua提供了一种加载和执行Lua脚本的接口。

开发人员可以使用XLua提供的API加载Lua脚本文件,然后在C#中通过XLua提供的接口执行脚本。

XLua 会将Lua脚本编译为字节码,并在Lua虚拟机中执行。

4. 交互操作:XLua允许在C#和Lua之间进行双向的交互操作。

开发人员可以通过在C#中注册函数、属性和委托,使其在Lua脚本中可用。

同样地,在Lua脚本中也可以调用C#的函数和属性,以实现对Unity游戏引擎的控制和访问。

总的来说,XLua的原理是通过将C#代码绑定到Lua环境中,提供Lua脚本的加载和执行接口,并实现C#与Lua之间的交互操作。

这使得开发人员可以利用Lua的灵活性和简洁性,扩展和定制Unity游戏的逻辑和功能。

Xlua对c#的vector3等结构体的优化

Xlua对c#的vector3等结构体的优化

Xlua对c#的vector3等结构体的优化⽬录:参考⽂章::⼀、lua如何操作Vector3,中间做了什么操作?1.获取Vector3对象由于Vector3的⽅法、属性都是成员⽅法、属性(如x、y、z、Slerp),那么调⽤这些⽅法前需要先获取Vector3对应的对象。

⽐如Vector3()新建、transform.position获取等。

以transform.position为例:_g_get_position⽅法创建了⼀个CSharpStruct类型的ud,并把x,y,z存在这个ud⾥。

这个ud的元表指向Vector3的obj_meta,通过这个元表可以访问Vector3Wrap注册的所有⽅法、属性,进⽽间接访问到Vector3。

ud ={["fake_id"] = -1["len"] = 12 //存储3个float值的⼤⼩,的对应xyz,float是4字节32位。

["data"][0] = x["data"][1] = y["data"][0] = z["__index"] = obj_meta}static int _g_get_position(RealStatePtr L){try {ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L);UnityEngine.Transform gen_to_be_invoked = (UnityEngine.Transform)translator.FastGetCSObj(L, 1);translator.PushUnityEngineVector3(L, gen_to_be_invoked.position);} catch(System.Exception gen_e) {return LuaAPI.luaL_error(L, "c# exception:" + gen_e);}return1;}public void PushUnityEngineVector3(RealStatePtr L, UnityEngine.Vector3 val){if (UnityEngineVector3_TypeID == -1){bool is_first;UnityEngineVector3_TypeID = getTypeId(L, typeof(UnityEngine.Vector3), out is_first);}//创建⼀个⼤⼩为(12+4+4)字节的userdata,元表Vector3的元表IntPtr buff = LuaAPI.xlua_pushstruct(L, 12, UnityEngineVector3_TypeID);if (!CopyByValue.Pack(buff, 0, val)) //把vector3拆成3个float传⼊cc,在c的结构体buff存储数据{throw new Exception("pack fail fail for UnityEngine.Vector3 ,value="+val);}}xlua.c⾥的接⼝:LUA_API void *xlua_pushstruct(lua_State *L, unsigned int size, int meta_ref) {CSharpStruct *css = (CSharpStruct *)lua_newuserdata(L, size + sizeof(int) + sizeof(unsigned int));css->fake_id = -1;css->len = size;lua_rawgeti(L, LUA_REGISTRYINDEX, meta_ref);lua_setmetatable(L, -2);return css;}LUALIB_API int xlua_pack_float3(void *p, int offset, float f1, float f2, float f3) {CSharpStruct *css = (CSharpStruct *)p;if (css->fake_id != -1 || css->len < offset + sizeof(float) * 3) {return0;} else {float *pos = (float *)(&(css->data[0]) + offset);pos[0] = f1;pos[1] = f2;pos[2] = f3;return1;}}2.设置transform.position代码如下:主要是UnPack⽅法调⽤xlua的xlua_unpack_float3⽅法,从上⾯的ud结构⾥取到x,y,c的值压栈并赋值给UnPack的x,y,z参数,再由UnPack组装⼀个新的Vevtor3返回给_s_set_position进⾏赋值。

api,gateway解决方案

api,gateway解决方案

api,gateway解决方案篇一:api-gateway 部署文档Api-gateway部署文档目录1. 安装环境 ................................................ ................................................... .. (1)Api-gateway服务器配置: .............................................. .. (1)Mysql安装 ................................................ ................................................... .. (2)创建数据库: .............................................. ................................................... (2)创建数据表: .............................................. ................................................... (2)tomcat安装配置 ................................................ ................................................... . (2)部署运用 ................................................ ................................................... .. (3)部署服务 ................................................ ................................................... .. (3)启动服务 ................................................ ................................................... .................... 3 2.1. 安装环境Api-gateway服务器配置:Mysql安装创建数据库:create databse oauth2;创建数据表:create table oauth_client_details ( client_id VARCHAR(255) PRIMARY KEY, resource_ids VARCHAR(256),client_secret VARCHAR(256),scope VARCHAR(256),authorized_grant_types VARCHAR(256), web_server_redirect_uri VARCHAR(256), authorities VARCHAR(256),access_token_validity INTEGER,refresh_token_validity INTEGER, additional_information VARCHAR(4096), autoapprove VARCHAR(256));tomcat安装配置下载tomcat并解压,修改conf/:protocol="" connectionTimeout="XX0" redirectPort="8443" />2. 部署运用部署服务修改autheserver配置文件=jdbc: =rideo=123456修改proxy配置文件: resource1: resource2: : 分别拷贝对应得war包到服务器tomcat的webapps目录下----->----->----->启动服务启动tomcat服务:cd bin./篇二:wso2 API 管理解决方案wso2 API 管理解决方案基础平台组XX年08月目录前言 ................................................ ................................................... (1)修订历史 ................................................ ................................................... (1)用户范围 ................................................ ................................................... (1)第1章概述................................................. ................................................... . (2)背景 ................................................ ................................................... .. (2)什么是API管理 ................................................ ................................................... . (2)API管理的作用 ................................................ ................................................... (2)加速API 的采用 ................................................ ................................................... (2)保护你的API ............................................... ................................................... . (2)将分析和报告转换为结果 ................................................ .. (2)提升API 的可发现性和可利用性 ................................................ .. (3)第2章简介................................................. ................................................... . (4)API MANAGER简介 ................................................ ................................................... (4)第3章关键概念 ................................................ ................................................... (5)API MANAGER组件 ................................................ ................................................... (5)API Publisher ......................................... ................................................... . (5)API Store ............................................. ................................................... . (6)API Gateway ........................................... ................................................... (7)KeyManager ........................................... ................................................... (7)Handlers .......................................... ................................................... .. (8)Statisticsc ....................................... ................................................... (9)USERS AND ROLES(用户及角色) .............................................. ................................................... (9)Admin(管理员) .............................................. ................................................... (9)Creator(创建者)............................................... ................................................... (10)Publisher(发布者) .............................................. ................................................... .. 10Subscriber(订阅者) .............................................. ...................................................10API LIFECYCLE(API 生命周期) .............................................. ................................................... (10)APPLICATIONS(应用程序) .............................................. ................................................... . (10)ACCESS TOKENS(访问令牌) .............................................. ................................................... .. (11)User access tokens(用户访问令牌)............................................... .. (11)Application access tokens(应用程序访问令牌) .............................................. .. (11)THROTTLING TIERS(节流层) .............................................. ................................................... .. (13)Different levels of throttling(不同级别的流量控制) ..............................................13API VISIBILITY AND SUBSCRIPTION(API 的可见性与订阅) .............................................. . (20)API visibility(API 的可见性) .............................................. .. (20)Subscription availability(订阅可用性) .............................................. . (20)API DOCUMENTATION VISIBILITY(API 文档的可见性) .............................................. . (21)API RESOURCES(API 资源) .............................................. ................................................... (22)URL Pattern(URL模式) .............................................. . (23)HTTP METHODS(HTTP 方法)............................................... ................................................... .. 24OAuth scopes(OAuth 范围) .............................................. .. (25)Authentication type(认证类型) .............................................. . (25)Response content type(响应内容类型) .............................................. (25)Parameters(参数) .............................................. ................................................... .. 25CROSS-ORIGIN RESOURCE SHARING(跨域资源共享) .............................................. (26)OAUTH SCOPES(OAUTH 范围) .............................................. ................................................... .. 27How scopes work(scopes 工作原理) .............................................. (27)Applying a scope(应用范围) .............................................. .. (28)Scope whitelisting(范围白名单) .............................................. .. (29)API TEMPLATES(API 模板) .............................................. ................................................... . (30)ENDPOINTS(端点)............................................... ................................................... . (30)SEQUENCES ......................................... ................................................... . (31)CACHING ........................................... ................................................... .. (31)第4章架构................................................. ................................................... .. (32)API MANAGER组件架构 ................................................ ................................................... (32)API MANAGER数据库架构 ................................................ ................................................... . (33)第5章多租户 ................................................ ................................................... .. (35)多租户架构 ................................................ ................................................... (35)架构 ................................................ ................................................... .. (35)约束 ................................................ ................................................... .. (38)请求调度 ................................................ ................................................... . (38)规模 ................................................ ................................................... (39)第6章集群部署模式 ................................................ ................................................... .. (40)分布式部署的主要组件 ................................................ ................................................... . (40)消息流 ................................................ ................................................... . (41)分布式部署模式 ................................................ ................................................... (42)Store 和Publisher组件在一个服务器节点 ................................................ .. (42)配置外部Store的最小集群 ................................................ (43)所有组件集群,内部部署 ................................................ (43)所有组件集群,配置外部Store ............................................. .. (44)第7章基本功能 ................................................ ................................................... . (46)创建以及发布API ............................................... ................................................... (46)订阅................................................... . (46)使用集成的API 控制台调用API ............................................... (46)使用SWAGGER UI编辑API ............................................... ................................................... (47)添加API 文档 ................................................ ................................................... .. (47)添加文档方法 ................................................ ................................................... . (47)添加基于Apache Solr 的索引 ................................................ .. (47)管理API 生命周................................................... (48)创建一个新版本API ............................................... ...................................................48部署并测试原型 ................................................ ................................................... (48)发布新版本、弃用旧版本 ................................................ (48)发布API 到多个外部API STORE ............................................. ................................................... .. 48通过多个API GATEWAY 发布API ............................................... ..................................................49使用新的节流策略 ................................................ ................................................... (49)阻塞API ............................................... ................................................... .. (49)执行节流和资源访问策略 ................................................ ................................................... . (50)使用自定义的中介流 ................................................ ................................................... (50)使用API PUBLISHER URL 映射为后端URL 的参数 ................................................ .. (50)SOAP 与JSON 消息转换 ................................................ ................................................... (50)在API 控制台中添加额外的消息头HEADER ............................................ . (51)使用社区特性 ................................................ ................................................... (51)使用SOAP 客户端调用API ............................................... ................................................... . (52)使用脚本创建原型API ............................................... ................................................... .. (52)传输自定义的授权令牌到后端 ................................................ .. (52)第8章统计分析 ................................................ ................................................... (53)发布API 运行时统计数据 ................................................ ................................................... (53)集成GOOGLE ANALYTICS ......................................... ................................................... . (53)查看API 统计数据 ................................................ ................................................... (53)第9章安全................................................. ................................................... .. (54)基于CARBON 平台的安全配置 ................................................ ...................................................54配置传输层安全 ................................................ ................................................... (54)配置密钥库 ................................................ ................................................... .. (54)敏感密码安全 ................................................ ................................................... . (54)启用JAVA 安全管理 ................................................ ..................................................55使用JWT 传输终端用户属性到后端 ................................................ . (55)加密安全的端点密码 ................................................ ................................................... .. (56)维护登录密码 ................................................ ................................................... .. (56)保存访问令牌 ................................................ ................................................... .. (56)配置IS 作为KEY MANAGER ........................................... ................................................... . (56)配置第三方KEY MANAGER ........................................... ................................................... .. (57)前言修订历史状态标识:C –Created A- Added M - Modified D - Deleted用户范围本文档根据wso2 API Manager 的官方文档编写,大部分内容源自对官方文档的翻译,并对内容作了排版,适合需要快速了解、使用wso2 API Manager的用户阅读。

XLua的配置

XLua的配置

xLua的配置xLua所有的配置都支持三种方式:打标签;静态列表;动态列表。

打标签xLua用白名单来指明生成哪些代码,而白名单通过attribute来配置,比如你想从lua调用c#的某个类,希望生成适配代码,你可以为这个类型打一个LuaCallCSharp标签:[LuaCallCSharp]public class A{}该方式方便,但在il2cpp下会增加不少的代码量,不建议使用。

静态列表有时我们无法直接给一个类型打标签,比如系统api,没源码的库,或者实例化的泛化类型,这时你可以在一个静态类里声明一个静态字段,该字段的类型除BlackList和AdditionalProperties之外只要实现了IEnumerable<Type>就可以了(这两个例外后面具体会说),然后为这字段加上标签:[LuaCallCSharp]public static List<Type> mymodule_lua_call_cs_list = new List<Type>(){typeof(GameObject),typeof(Dictionary<string, int>),};这个字段需要放到一个静态类里头,建议放到Editor目录。

动态列表声明一个静态属性,打上相应的标签即可。

[Hotfix]public static List<Type> by_property{get{return (from type in Assembly.GetExecutingAssembly().GetTypes()where space == "XXXX"select type).ToList();}}Getter是代码,你可以实现很多效果,比如按名字空间配置,按程序集配置等等。

这个属性需要放到一个静态类里头,建议放到Editor目录。

XLua.LuaCallCSharp一个C#类型加了这个配置,xLua会生成这个类型的适配代码(包括构造该类型实例,访问其成员属性、方法,静态属性、方法),否则将会尝试用性能较低的反射方式来访问。

XLua增加删除第三方lua库

XLua增加删除第三方lua库

What&WhyXLua目前内置的扩展库:1、针对luajit的64位整数支持;2、函数调用耗时以及内存泄漏定位工具;3、用于支持ZeroBraneStudio的luasocket库;4、tdr 4 lua;随着使用项目的增加以及项目使用的深入程度,仅有这几个扩展已经没法满足项目组了,而由于各个项目对扩展差异化比较大,以及手机平台对安装包大小的敏感,XLua是无法通过预集成去满足这些需求,这也是这篇教程的由来。

这篇教程,将以lua-rapidjson为例,一步步的讲述怎么往xLua添加c/c++扩展,当然,会添加了,自然删除也就会了,项目组可以自行删除不需要用到的预集成扩展。

How分三步1、修改build文件、工程设置,把要集成的扩展编译到XLua Plugin里头;2、调用xLua的C# API,使得扩展可以被按需(在lua代码里头require的时候)加载;3、可选,如果你的扩展里头需要用到64位整数,你可以通过XLua的64位扩展库来实现和C#的配合。

一、添加扩展&编译准备工作把xLua的C源码包解压到你Unity工程的Assets同级目录下。

下载lua-rapidjson代码,按你的习惯放置。

本教程是把rapidjson头文件放到$UnityProj\build\lua-rapidjson\include目录下,而扩展的源码rapidjson.cpp放到$UnityProj\build\lua-rapidjson\source目录下(注:$UnityProj指的是你工程的目录)在CMakeLists.txt加入扩展xLua的各平台Plugins编译使用cmake编译,好处是所有平台的编译都写在一个makefile,大部分编译处理逻辑是跨平台的。

xLua配套的CMakeLists.txt为第三方扩展提供了扩展点(都是list):THIRDPART_INC:第三方扩展的头文件搜索路径。

fireworks的api说明

fireworks的api说明

一、Fireworks API 简介Fireworks API 是一个功能强大的工具,用于管理和操作 Fireworks 评台上的数据和资源。

它提供了一组丰富的接口,可以方便地实现数据的增删改查、权限管理、文件存储和访问控制等功能。

Fireworks API 设计灵活、易于扩展,支持多种编程语言和开发环境,为开发者提供了丰富的选择。

下面将逐步介绍 Fireworks API 的使用方法和注意事项。

二、Fireworks API 的基本概念1. 接口概述Fireworks API 提供了一系列 RESTful 风格的接口,以 HTTP 请求和响应的方式进行通信。

开发者可以通过发送请求来调用 API 中定义的各种功能,比如创建资源、更新数据、查询信息等。

API 会返回相应的结果或错误信息,从而实现客户端与服务器端的数据交换和操作。

2. 认证机制为了保障数据的安全和隐私,Fireworks API 提供了多种认证方式,包括基本认证、OAuth2.0 认证、API 密钥认证等。

开发者需要在调用API 时使用相应的认证信息,以便服务器能够正确识别和验证用户的身份,并控制其权限和访问范围。

3. 数据格式Fireworks API 支持多种数据格式,包括 JSON、XML、Form 表单等。

开发者可以根据自己的需求选择合适的数据格式,与 API 进行数据交换和传输。

API 会在响应中包含相应的数据格式,以便客户端进行解析和处理。

三、Fireworks API 的基本用法1. API 文档Fireworks API 提供了详细的文档和示例,包括接口说明、参数说明、使用示例等。

开发者可以通过查阅文档来了解API 的功能和使用方法,从而更好地进行开发和测试。

API 文档通常包含了各种资源、端点和操作的描述,为开发者提供了参考和指导。

2. 发送请求开发者可以使用各种 HTTP 客户端工具或框架,通过发送请求来调用Fireworks API 中的各种功能。

UnityXLua官方教程学习

UnityXLua官方教程学习

UnityXLua官⽅教程学习⼀、Lua ⽂件加载1. 执⾏字符串1using UnityEngine;2using XLua;34public class ByString : MonoBehaviour {5 LuaEnv luaenv = null;6// Use this for initialization7void Start () {8 luaenv = new LuaEnv();9// 执⾏代码块,输出 hello world10 luaenv.DoString("print('hello world')");11 }1213// Update is called once per frame14void Update () {15if (luaenv != null)16 {17// 清楚 Lua 未⼿动释放的 LuaBase 对象18 luaenv.Tick();19 }20 }2122void OnDestroy()23 {24// 销毁25 luaenv.Dispose();26 }27 } 其中 Dostring 函数返回值即为代码块⾥ return 语句的返回值。

2. 加载 Lua ⽂件1 luaenv = new LuaEnv();2// 加载 byfile Lua ⽂件3 luaenv.DoString("require 'byfile'"); 其中 Lua ⽂件代码为:print('hello world') 需要注意的是因为 Resource 只⽀持有限的后缀,放 Resources 下 lua ⽂件得加上 txt 后缀,如:byfile.lua.txt。

3. ⾃定义 Loader1void Start()2 {3 luaenv = new LuaEnv();4// ⾃定义 loader5 luaenv.AddLoader((ref string filename) => {6// 若要加载 InMemory7if (filename == "InMemory")8 {9string script = "return {ccc = 9999}";10// 将字符串转换成byte[]11return System.Text.Encoding.UTF8.GetBytes(script);12 }13return null;14 });15// 执⾏代码块,访问table中的常量ccc16 luaenv.DoString("print('c=', require('InMemory').ccc)");17 } 通过 Addloader 可以注册个回调,该回调参数是字符串,返回⼀个 byte 数组。

toLua与Xlua使用方法总结

toLua与Xlua使用方法总结

toLua与Xlua使⽤⽅法总结两者都是常见的基于Unity的热更需求开发出来成熟⽅案。

实现原理是在Unity启动后加载⼀个lua虚拟机。

解释lua脚本。

再通过各种⽅法⽀持C# <> lua 层的互相调⽤。

委托。

反射。

传值传址调⽤。

本处只作为初学者对⽐⼀下双⽅在上⼿和使⽤时候的⼀些异同。

以两种⽅法实现的跳⼀跳⼩游戏为例。

⼀ lua配置和exaple⽰例1. tolua2 xlua⼆ lua Wrap⽂件⽣成⽅法1 tolua 根据配置⽂件CustomSetting 指定相关的输出⽬录需要注册委托的类。

事件。

类型等2 xlua 3种⽅式进⾏配置。

1) 使⽤标签[CSharpCallLua] / [LuaCallCSharp] ⾃动识别对应的类和⽅法。

2) 静态配置⽂件统⼀配置3) 动态配置三 lua启动环境和C#调⽤lua1 tolua 全局统⼀的LuaClient。

直接加载lua⽂件.使⽤*.lua⽂件public class LuaManager : MonoBehaviour {private static LuaManager _instance;public static LuaManager Instance{get{return _instance;}}private LuaClient _luaClient;public LuaClient LuaClient{get{return _luaClient;}}// Use this for initializationvoid Awake () {_instance = this;DontDestroyOnLoad(this.gameObject);_luaClient = this.gameObject.AddComponent<LuaClient>();}}//使⽤DoFile调⽤lua,使⽤CallFunc调⽤lua函数LuaManager.Instance.LuaClient.luaState.DoFile("Login.lua");LuaManager.Instance.LuaClient.CallFunc("Login.Awake", this.gameObject);2 xlua 也是初始化1个luaenv后。

XLua(热更新)的基础使用

XLua(热更新)的基础使用

XLua(热更新)的基础使⽤
在官⽅下在xlua框架,将Asset⾥⾯的两个⽂件夹,Plugins和XLua拖到⼯程⽬录⾥,这样就完成对xlua的导⼊
接下来先从xlua的⼀些简单语法开始
⾸先是这个Lua虚拟机类,官⽅建议全局只有⼀个,因为消耗性能
上⾯的代码会直接从lua⾥输出这段字符
那么我们如何使⽤xLua来获得⼀个lua脚本呢,下⾯就来演⽰⼀下,
先新建个lua脚本,格式为⽂件名+.lua+.txt,然后放在 Resources⽂件夹下⾯
lua 脚本只输出⼀句话,那么我们可以使⽤"require "关键字来找到lua 脚本,后⾯只要加上脚本名
然后来讲下c#如何调⽤lua⾥的变量,在这之前,需要先来修改下之前的lua脚本
⾥⾯定义了三种变量和⼀个⽅法,现在回到C# 中开始写代码来获取
很简单,基本就是利⽤luaEnv.Global.Get<T>来取得变量,函数取得就是使⽤LuaFunction myName 下⾯来输出这些从lua⾥获取到的数据
这样就可以运⾏后看到控制台输出的值
好了,前⾯的都是简单的C#调⽤lua的数据,那现在来讲讲如何从lua中来调⽤C#的类和⽅法
⾸先为了⽅便,就直接在脚本前⾯加上这⼏句lua代码
就是在在调⽤C#类命名空间前要加上"CS",这样就可以调⽤C#的函数,下⾯来调⽤这些脚本执⾏
成功输出了C#类⾥的数据,也创建了个新的空物体,并给定名字。

xlua热更新的实现原理

xlua热更新的实现原理

xlua热更新的实现原理
XLua 是一个使用C# 开发的Lua 虚拟机,它使用JIT(即时编译)编译器,并提供了丰富的API 来实现Lua 与C#通信,支持Lua 热更新。

热更新的原理是使用新的字节码覆盖或替换掉当前运行时的字节码,实现状态的无缝更新。

XLua 的热更新实现原理如下:
1. 首先,XLua 采用动态编译的方式,根据需要将Lua 源代码编译成汇编的字节码。

有了这些编译后的字节码就可以在运行时进行动态加载。

2. 热更新本质上是将这些字节码内容由旧的覆盖成新的,所以我们需要做到实现热更新时,替换出来的新字节码与旧字节码不同。

3. XLua 内置了一个热更新框架,可以根据对比旧新字节码之间的差异,自动执行更新操作,从而实现热更新。

4. 这里还有一个关键的细节:在处理热更新完成后,XLua 通过比较模块的版本、字节码的大小和偏移,在不加载完整字节码的前提下,还能做出非常有效的补丁处理。

以上就是XLua 热更新实现原理简介。

XLua 的热更新特性方便了开发者在程
序运行中不停止运行就可以使修改内容可以在不重启游戏的情况下生效,大大减少了更新测试成本。

XLua使用教程

XLua使用教程

xLua教程Lua文件加载一、执行字符串最基本是直接用LuaEnv.DoString执行一个字符串,当然,字符串得符合Lua语法比如:luaenv.DoString("print('hello world')")完整代码见XLua\Tutorial\LoadLuaScript\ByString目录但这种方式并不建议,更建议下面介绍这种方法。

二、加载Lua文件用lua的require函数即可比如:DoString("require 'byfile'")完整代码见XLua\Tutorial\LoadLuaScript\ByFile目录require实际上是调一个个的loader去加载,有一个成功就不再往下尝试,全失败则报文件找不到。

目前xLua除了原生的loader外,还添加了从Resource加载的loader,需要注意的是因为Resource只支持有限的后缀,放Resources下的lua文件得加上txt后缀(见附带的例子)。

建议的加载Lua脚本方式是:整个程序就一个DoString("require 'main'"),然后在main.lua加载其它脚本(类似lua脚本的命令行执行:lua main.lua)。

有童鞋会问:要是我的Lua文件是下载回来的,或者某个自定义的文件格式里头解压出来,或者需要解密等等,怎么办?问得好,xLua的自定义Loader可以满足这些需求。

三、自定义Loader在xLua加自定义loader是很简单的,只涉及到一个接口:public delegate byte[] CustomLoader(ref string filepath);public void LuaEnv.AddLoader(CustomLoader loader)通过AddLoader可以注册个回调,该回调参数是字符串,lua代码里头调用require时,参数将会透传给回调,回调中就可以根据这个参数去加载指定文件,如果需要支持调试,需要把filepath修改为真实路径传出。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C# APILuaEnv类object[] DoString(string chunk, string chunkName = "chuck", LuaTable env = null)描述:执行一个代码块。

参数:chunk: Lua代码文字串;chunkName:发生error时的debug显示信息中使用,指明某某代码块的某行错误;env :这个代码块的环境变量;返回值:代码块里return语句的返回值;比如:return 1, “hello”,DoString返回将包含两个object的数组,一个是double类型的1,一个是string类型的“hello”例子:LuaEnv luaenv = new LuaEnv();object[] ret = luaenv.DoString("print(‘hello’)\r\nreturn 1")UnityEngine.Debug.Log("ret="+ret[0]);luaenv.Dispose()T LoadString<T>(string chunk, string chunkName = "chunk", LuaTable env = null)描述:加载一个代码块,但不执行,只返回类型可以指定为一个delegate或者一个LuaFunction参数:chunk: Lua代码的字符串;chunkName:发生error时的debug显示信息中使用,指明某某代码块的某行错误;env :这个代码块的环境变量;返回值:代表该代码块的delegate或者LuaFunction类;LuaTable Global;描述:代表lua全局环境的LuaTablevoid Tick()描述:清除Lua的未手动释放的LuaBase对象(比如:LuaTable, LuaFunction),以及其它一些事情。

需要定期调用,比如在MonoBehaviour的Update中调用。

void AddLoader(CustomLoader loader)增加一个自定义loader参数:loader:一个包含了加载函数的委托,其类型为delegate byte[] CustomLoader(ref string filepath),当一个文件被require时,这个loader会被回调,其参数是调用require所使用的参数,如果该loader找到文件,可以将其读进内存,返回一个byte数组。

如果需要支持调试的话,而filepath要设置成IDE能找到的路径(相对或者绝对都可以)void Dispose()描述:Dispose该LuaEnv。

LuaEnv的使用建议:全局就一个实例,并在Update中调用GC方法,完全不需要时调用Dispose LuaTable类T Get<T>(string key)描述:获取在key下,类型为T的value,如果不存在或者类型不匹配,返回null;T GetInPath<T>(string path)描述:和Get的区别是,这个函数会识别path里头的“.”,比如var i = tbl.GetInPath<int>(“a.b.c”)相当于在lua里头执行i = tbl.a.b.c,避免仅为了获取中间变量而多次调用Get,执行效率更高。

void SetInPath<T>(string path, T val)描述:和GetInPaht<T>对应的setter;void Get<TKey, TValue>(TKey key, out TValue value)描述:上面的API的Key都只能是string,而这个API无此限制;void Set<TKey, TValue>(TKey key, TValue value)描述:对应Get<TKey, TValue>的setter;T Cast<T>()描述:把该table转成一个T指明的类型,可以是一个加了CSharpCallLua声明的interface,一个有默认构造函数的class或者struct,一个Dictionary,List等等。

void SetMetaTable(LuaTable metaTable)设置metaTable为table的metatableLuaFunction类注意:用该类访问Lua函数会有boxing,unboxing的开销,为了性能考虑,需要频繁调用的地方不要用该类。

建议通过table.Get<ABCDelegate>获取一个delegate再调用(假设ABCDelegate是C#的一个delegate)。

在使用使用table.Get<ABCDelegate>之前,请先把ABCDelegate加到代码生成列表。

object[] Call(params object[] args)描述:以可变参数调用Lua函数,并返回该调用的返回值。

object[] Call(object[] args, Type[] returnTypes)描述:调用Lua函数,并指明返回参数的类型,系统会自动按指定类型进行转换。

void SetEnv(LuaTable env)描述:相当于lua的setfenv函数。

Lua APICS对象space.class(...)描述:调用一个C#类型的构造函数并返回实例对象,例如:local v1=CS.UnityEngine.Vector3(1,1,1)space.class.field描述:访问一个C#静态成员,例如:Print(CS.UnityEngine.Vector3.one)space.enum.field描述:访问一个枚举值typeof函数类似C#里头的typeof关键字,返回一个Type对象,比如GameObject.AddComponent其中一个重载需要一个Type参数,这时可以这么用newGameObj:AddComponent(typeof(CS.UnityEngine.ParticleSystem))无符号64位支持uint64.tostring描述:无符号数转字符串。

uint64.divide描述:无符号数除法。

pare描述:无符号比较,相对返回0,大于返回正数,小于返回负数。

uint64.remainder描述:无符号数取模。

uint64.parse描述:字符串转无符号数。

xlua.structclone描述:克隆一个c#结构体xlua.private_accessible(class)描述:让一个类的私有字段,属性,方法等可用cast函数指明以特定的接口访问对象,这在实现类无法访问的时候(比如internal修饰)很有用,这时可以这么来(假设下面的calc对象实现了C#的PerformentTest.ICalc接口):cast(calc, typeof(CS.PerformentTest.ICalc))然后就木有其它API了访问csharp对象和访问一个table一样,调用函数跟调用lua函数一样,也可以通过操作符访问c#的操作符,下面是一个例子:local v1=CS.UnityEngine.Vector3(1,1,1)local v2=CS.UnityEngine.Vector3(1,1,1)v1.x = 100v2.y = 100print(v1, v2)local v3 = v1 + v2print(v1.x, v2.x)print(CS.UnityEngine.Vector3.one)print(CS.UnityEngine.Vector3.Distance(v1, v2))类型映射基本数据类型C#类型Lua类型sbyte,byte,short,ushort,int,uint,double,char,float numberdecimal userdatalong,ulong userdata/lua_Integer(lua53)bytes[] stringbool booleanstring string复杂数据类型C#类型Lua类型LuaTable tableLuaFunction functionclass或者 struct的实例userdata,tablemethod,delegate functionLuaTable:C#侧指明从Lua侧输入(包括C#方法的输入参数或者Lua方法的返回值)LuaTable类型,则要求Lua 侧为table。

或者Lua侧的table,在C#侧未指明类型的情况下转换成LuaTable。

LuaFunction:C#侧指明从Lua侧输入(包括C#方法的输入参数或者Lua方法的返回值)LuaFunction类型,则要求Lua侧为function。

或者Lua侧的function,在C#侧未指明类型的情况下转换成LuaFunction。

LuaUserData:对应非C# Managered对象的lua userdata。

class或者 struct的实例:从C#传一个class或者struct的实例,将映射到Lua的userdata,并通过__index访问该userdata 的成员C#侧指明从Lua侧输入指定类型对象,Lua侧为该类型实例的userdata可以直接使用;如果该指明类型有默认构造函数,Lua侧是table则会自动转换,转换规则是:调用构造函数构造实例,并用table 对应字段转换到c#对应值后赋值各成员。

method, delegate:成员方法以及delegate都是对应lua侧的函数。

C#侧的普通参数以及引用参数,对应lua侧函数参数;C#侧的返回值对应于Lua的第一个返回值;引用参数和out参数则按序对应于Lua的第2到第N个参数。

相关文档
最新文档