欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:XLua原理(一)

柚子快報激活碼778899分享:XLua原理(一)

http://yzkb.51969.com/

項目中活動都是用xlua開發(fā)的,項目周更熱修也是用xlua的hotfix特性來做的?,F(xiàn)研究底層原理,對于項目性能有個更好的把控。

本文認(rèn)為看到該文章的人已具備使用xlua開發(fā)的能力,只研究介紹下xlua的底層實現(xiàn)原理。

一.lua和c#交互原理

概括:

通過棧來實現(xiàn)。lua調(diào)用c#就是將lua層的參數(shù)和c#導(dǎo)出函數(shù)入棧,然后執(zhí)行函數(shù)。c#調(diào)用lua就是將c#層的參數(shù)和lua函數(shù)入棧,然后執(zhí)行函數(shù)

1.1 C#訪問lua

直接上代碼:

private void Demo1()

{

IntPtr L = LuaAPI.luaL_newstate();

if (LuaAPI.luaL_loadbuffer(L, @"function addandsub(x,y)

return x+y , x-y end", "selfTagChunk") != 0)

{

Debug.LogError(LuaAPI.lua_tostring(L,-1));

}

//LuaAPI.lua_pushnumber(L,20);

//LuaAPI.lua_pushnumber(L,21);

LuaAPI.lua_pcall(L, 0, 0, 0);

LuaAPI.xlua_getglobal(L, "addandsub");

LuaAPI.lua_pushnumber(L,10);

LuaAPI.lua_pushnumber(L,7);

int valueB = LuaAPI.xlua_tointeger(L, -1);//7

int valueB2 = LuaAPI.xlua_tointeger(L, -2);//10

LuaTypes luaTypeB3 = LuaAPI.lua_type(L, -3);//function

int valueC4 = LuaAPI.xlua_tointeger(L, 3);//7

int valueC3 = LuaAPI.xlua_tointeger(L, 2);//10

LuaTypes luaTypeC2 = LuaAPI.lua_type(L, 1);//function

if (LuaAPI.lua_pcall(L, 2, 2, 0) != 0)

{

Debug.LogError(LuaAPI.lua_tostring(L,-1));

}

int value = LuaAPI.xlua_tointeger(L, -1); //3

int value2 = LuaAPI.xlua_tointeger(L, -2); //17

LuaAPI.lua_close(L);

}

Api備注:

LuaAPI.luaL_newstate:開辟lua虛擬機(jī),執(zhí)行l(wèi)ua程序 LuaAPI.lua_close:關(guān)閉lua虛擬機(jī),釋放資源 LuaAPI.luaL_loadbuffer:編譯一段lua代碼,但沒執(zhí)行 LuaAPI.lua_pcall:執(zhí)行l(wèi)ua代碼,這時候可以用

這里:先把addandsub方法壓棧,然后把10和7分別壓棧。所以看到的內(nèi)存里的數(shù)據(jù)如批注所示。

在執(zhí)行第2個lua_pcall。會把之前的堆棧信息清空,把函數(shù)執(zhí)行返回的結(jié)果進(jìn)行壓棧操作

1.2 lua訪問C#

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]

public delegate void TestCSFunction(IntPtr L);

[MonoPInvokeCallback(typeof(TestCSFunction))]

public static void TestLuaCallCSharp(IntPtr L)

{

Debug.Log("TestLuaCallCSharp");

}

private void Demo2()

{

IntPtr L = LuaAPI.luaL_newstate();

//Marshal 提供對非托管類型的操作

IntPtr function = Marshal.GetFunctionPointerForDelegate(new TestCSFunction(TestLuaCallCSharp));

//函數(shù)入棧

LuaAPI.lua_pushcclosure(L,function,0);

LuaAPI.lua_pcall(L, 0, 0, 0);

LuaAPI.lua_close(L);

}

UnmanagedFunctionPointer:定義為了讓其不受C#托管管理 MonoPInvokeCallback:標(biāo)記可以使其用C或C++調(diào)用

上述可以看到是把C#函數(shù)包裝成指針,然后進(jìn)行壓棧操作供lua調(diào)用

二.xlua中的LuaEnv

private void Demo3()

{

LuaEnv luaenv = new LuaEnv();

luaenv.DoString("CS.UnityEngine.Debug.Log('hello world')");

luaenv.Dispose();

}

LuaEnv:是xlua封裝好的lua環(huán)境,類似上面的luaL_newstate。

具體的事情:

XLua框架中最重要的一個類,那就是LuaEnv。它包含了lua中的狀態(tài)機(jī)RealStatePrt。lua的G表,還有注冊表LuaIndexes.LUA_REGISTRYINDEX等等,下面從LuaEnv的構(gòu)造函數(shù)開始,看看這個類做了些什么事情

//節(jié)選LuaEnv構(gòu)造函數(shù)部分代碼

//拿到Lua中的注冊表

LuaIndexes.LUA_REGISTRYINDEX = LuaAPI.xlua_get_registry_index

//創(chuàng)建Lua狀態(tài)機(jī)

rawL = LuaAPI.luaL_newstate()

//十分重要的一個對象,用于c#和lua的交互

translator = new ObjectTranslator(this, rawL);

translator.createFunctionMetatable(rawL); //添加_gc元方法到注冊表

translator.OpenLib(rawL); //將init_xlua中會用到的方法,全部定義出來

//添加搜索路徑

AddSearcher(StaticLuaCallbacks.LoadBuiltinLib, 2);

//添加自定義解析Lua文件的方法,對應(yīng)的是LuaEnv.CustomLoader

AddSearcher(StaticLuaCallbacks.LoadFromCustomLoaders, 3);

#if !XLUA_GENERAL

AddSearcher(StaticLuaCallbacks.LoadFromResource, 4);

AddSearcher(StaticLuaCallbacks.LoadFromStreamingAssetsPath, -1);

#endif

//十分重要?。?初始化xLua

DoString(init_xlua, "Init");

#if !UNITY_SWITCH || UNITY_EDITOR

AddBuildin("socket.core", StaticLuaCallbacks.LoadSocketCore);

AddBuildin("socket", StaticLuaCallbacks.LoadSocketCore);

#endif

AddBuildin("CS", StaticLuaCallbacks.LoadCS);

調(diào)用Init方法:

private string init_xlua = @"

local metatable = {}

local rawget = rawget

local setmetatable = setmetatable

local import_type = xlua.import_type

local import_generic_type = xlua.import_generic_type

local load_assembly = xlua.load_assembly

--fqn就是類型和命名空間名,通過import_type去獲取對應(yīng)的udata并且入棧

function metatable:__index(key)

--查詢key不調(diào)用元方法,更簡單的表達(dá)只在自己的表內(nèi)查詢

local fqn = rawget(self,'.fqn')

fqn = ((fqn and fqn .. '.') or '') .. key

--查詢C#類型

local obj = import_type(fqn)

--如果不是 再次查詢C#命名空間

if obj == nil then

-- It might be an assembly, so we load it too.

obj = { ['.fqn'] = fqn }

setmetatable(obj, metatable)

elseif obj == true then

return rawget(self, key)

end

-- Cache this lookup

rawset(self, key, obj)

return obj

end

--既然是C#對象 就不要再newindex了,避免產(chǎn)生未知的錯誤

function metatable:__newindex()

error('No such type: ' .. rawget(self,'.fqn'), 2)

end

-- A non-type has been called; e.g. foo = System.Foo()

function metatable:__call(...)

local n = select('#', ...)

local fqn = rawget(self,'.fqn')

if n > 0 then

local gt = import_generic_type(fqn, ...)

if gt then

return rawget(CS, gt)

end

end

error('No such type: ' .. fqn, 2)

end

CS = CS or {}

setmetatable(CS, metatable)

--定義typeof 這下知道了 typeof是xlua自己搞的,不是lua本身語言特性

typeof = function(t) return t.UnderlyingSystemType end

cast = xlua.cast

if not setfenv or not getfenv then

local function getfunction(level)

local info = debug.getinfo(level + 1, 'f')

return info and info.func

end

function setfenv(fn, env)

if type(fn) == 'number' then fn = getfunction(fn + 1) end

local i = 1

while true do

local name = debug.getupvalue(fn, i)

if name == '_ENV' then

debug.upvaluejoin(fn, i, (function()

return env

end), 1)

break

elseif not name then

break

end

i = i + 1

end

return fn

end

function getfenv(fn)

if type(fn) == 'number' then fn = getfunction(fn + 1) end

local i = 1

while true do

local name, val = debug.getupvalue(fn, i)

if name == '_ENV' then

return val

elseif not name then

break

end

i = i + 1

end

end

end

xlua.hotfix = function(cs, field, func)

if func == nil then func = false end

local tbl = (type(field) == 'table') and field or {[field] = func}

for k, v in pairs(tbl) do

local cflag = ''

if k == '.ctor' then

cflag = '_c'

k = 'ctor'

end

local f = type(v) == 'function' and v or nil

xlua.access(cs, cflag .. '__Hotfix0_'..k, f) -- at least one

pcall(function()

for i = 1, 99 do

xlua.access(cs, cflag .. '__Hotfix'..i..'_'..k, f)

end

end)

end

xlua.private_accessible(cs)

end

xlua.getmetatable = function(cs)

return xlua.metatable_operation(cs)

end

xlua.setmetatable = function(cs, mt)

return xlua.metatable_operation(cs, mt)

end

xlua.setclass = function(parent, name, impl)

impl.UnderlyingSystemType = parent[name].UnderlyingSystemType

rawset(parent, name, impl)

end

local base_mt = {

__index = function(t, k)

local csobj = t['__csobj']

local func = csobj['<>xLuaBaseProxy_'..k]

return function(_, ...)

return func(csobj, ...)

end

end

}

base = function(csobj)

return setmetatable({__csobj = csobj}, base_mt)

end

";

設(shè)置了metatble擴(kuò)充原方法,并且設(shè)置CS的元表示metatable:

__index:會把C#沒有緩存的命名空間下的元數(shù)據(jù)導(dǎo)入進(jìn)來。

__call:與index同理,這里能看出來了為什么在lua里調(diào)C#方法是CS.UnityEngine.Vector3(x,x,x)。

這步是讓lua可以去訪問C#對象。

因為在Lua中定義了全局的CS表,并且在lua中調(diào)用CS的時候,會先調(diào)用StaticLuaCallbacks.LoadCS獲取到注冊表中的CS表,然后在調(diào)用XXX的時候,如果訪問到了CS表中不存在的元素,則會調(diào)用其元表,在元表中通過映射到c#的StaticLuaCallbacks.ImportType方法完成查找。

lua在查找時調(diào)用了import_type進(jìn)行查找調(diào)用,提前在OpenLib里把方法進(jìn)行注冊:

而importType會從中轉(zhuǎn)器查詢,查詢的過程就是從一個維護(hù)的字典里看能不能取到,取不到就加載命名空間并注入到lua虛擬機(jī)中。

后面介紹lua與C#之間通信會詳解介紹

參考:

Lua與C#交互原理(轉(zhuǎn))_lua與c#的交互原理-CSDN博客

https://zhuanlan.zhihu.com/p/441169478

柚子快報激活碼778899分享:XLua原理(一)

http://yzkb.51969.com/

好文閱讀

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19307688.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄