[英]How to use setmetatable to create a Lua wrapper class around a C# object
我正在為當前正在使用C#開發的游戲創建一些UI,並且希望將所有內容公開到Lua,以便我的美術師可以進行細微調整而無需執行任何代碼。 我正在使用MoonSharp將Lua腳本集成到我的項目中。
這是我目前為UIElement包裝器類提供的內容:
UIElement = {};
UIElement.__index = UIElement;
setmetatable( UIElement, {
__index = function( self, key )
local codeElement = rawget( self, "__codeElement" );
local field = codeElement and codeElement[key];
if type( field ) == "function" then
return function( obj, ... )
if obj == self then
return field( codeElement, ... );
else
return field( obj, ... )
end
end;
else
return field;
end
end,
__call = function( cls, ... )
return cls.new( ... );
end,
} );
function UIElement.new()
local self = setmetatable( {}, UIElement );
self.__codeElement = BLU_UIElement.__new();
return self;
end
BLU_UIElement是我的C#類,它通過MoonSharp API向Lua公開。 直接與對象一起使用時,它可以正常工作,並具有SetPos,SetColor等功能。
UIElement是我在Lua中的“類”,用於包裝和擴展C#對象。
當我在腳本中的其他地方實例化UIElement並嘗試調用一個函數(例如SetPos)時,它確實正確進入了__index函數。 但是,rawget調用始終返回nil。 它似乎也不特定於BLU_UIElement。 我已經嘗試過非常簡單的操作,例如在構造函數中添加字符串ID值,並嘗試在__index函數中將其原始獲取,但它也返回nil。
我假設我只是在做一些錯誤地在類或對象本身上設置亞穩態,但是我不確定問題出在哪里。 我一直在這里查看: http : //lua-users.org/wiki/ObjectOrientationTutorial ,以獲取有關我做錯了什么的想法,但是我什么都沒跳。
我對此表示感謝,我一直在研究這幾天,卻沒有弄清楚它,並且在線搜索通常只顯示與我已經在做的類似的代碼。
我必須承認我並不完全確定,您試圖通過在LUA(而不是C#)中編寫包裝器類,然后公開該類型來實現的目的,但是我注意到了這一點:
對我而言, NativeClass .__ new()從未在MoonSharp中解決過,就像您嘗試在
self.__codeElement = BLU_UIElement.__new();
因此,我為本機類創建了自定義構造函數,並將它們作為委托傳遞給全局名稱空間(盡管它的類型必須注冊)。 看起來很像您通常會構造一個對象。 沒有新關鍵字:
在C#中
public NativeClass{
public static NativeClass construct()
{
return new NativeClass();
}
}
將靜態方法作為委托傳遞給腳本:
script["NativeClass"] = (Func<NativeClass>)NativeClass.construct;
然后,您可以在MoonSharp中創建一個新的實例,如下所示:
x = NativeClass()
編輯:所以沒有讀到您嘗試使用字符串執行此操作。 也許您應該考慮不使用LUA而是使用C#編寫包裝類,還是有禁止該包裝的原因?
我有一個朋友,他對Lua元表的使用遠勝於我。 在這里發布答案,以防其他人受益。
問題是我試圖將UIElement表既用作“類”表又用作“對象”元表。 在__index函數中調用rawget時,它試圖在UIElement表中查找內容,而不是在UIElement.new()中創建的self表中查找內容。 將這兩個拆分成不同的表(一個用於類,一個用於對象元表)可以修復問題。
這是我更新的工作代碼:
UIElement = {};
setmetatable( UIElement, {
__call = function( cls, ... )
return cls.new( ... );
end,
} );
UIElement.objectMetaTable = {
__index = function( self, key )
local objectValue = rawget(self, key);
if objectValue ~= nil then
return objectValue;
end
local classValue = UIElement[key];
if classValue ~= nil then
return classValue;
end
local codeElement = rawget(self, "__codeElement");
if codeElement then
return codeElement[key];
end
end,
};
function UIElement.new()
local newInstance = setmetatable( { id = "blah" }, UIElement.objectMetaTable );
newInstance.__codeElement = BLU_UIElement.__new();
return newInstance;
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.