簡體   English   中英

如何使用setmetatable圍繞C#對象創建Lua包裝器類

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM