Как использовать setmetatable для создания класса-оболочки Lua вокруг объекта C # - PullRequest
1 голос
/ 20 апреля 2019

Я создаю некоторый пользовательский интерфейс для игры, над которой я сейчас работаю, в C #, и хочу показать все на 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 #, который предоставляется Lua через API MoonSharp. Он работает правильно при работе непосредственно с объектом и имеет такие функции, как SetPos, SetColor и т. Д.

UIElement предназначен для моего "класса" в Lua, чтобы обернуть и расширить мой объект C #.

Когда я создаю экземпляр UIElement в другом месте скрипта и пытаюсь вызвать функцию (например, SetPos), он правильно попадает в функцию __index. Однако вызов rawget всегда возвращает ноль. Это не кажется специфичным для элемента BLU_UIE. Я уже пробовал что-то очень простое, например, добавление значения идентификатора строки в конструкторе и попытка получить его в функции __index, но оно также возвращает nil.

Я предполагаю, что просто делаю что-то неправильно, настраивая метастабильность либо для класса, либо для самого объекта, но я не совсем уверен, в чем проблема. Я искал здесь: http://lua -users.org / wiki / ObjectOrientationTutorial , чтобы получить представление о том, что я делаю неправильно, но у меня ничего не выскакивает.

Я ценю любые рекомендации по этому поводу, я смотрел на это пару дней, не понимая этого, и поиск в Интернете, как правило, просто показывает код, аналогичный тому, что я уже делаю.

Ответы [ 2 ]

0 голосов
/ 15 мая 2019

У меня был друг, у которого гораздо больше опыта работы с мета-таблицами Lua, чем я смотрю.Публикация ответа здесь на тот случай, если он кому-нибудь поможет.

Проблема заключалась в том, что я пытался использовать таблицу UIElement как таблицу «class», так и метатабельный объект «object».При вызове rawget внутри функции __index он пытался найти вещи в таблице UIElement вместо таблицы self, созданной в UIElement.new ().Разделение этих двух таблиц на отдельные таблицы (одна для класса, другая для объекта с метатизацией) исправило некоторые вещи.

Вот мой обновленный и рабочий код:

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
0 голосов
/ 14 мая 2019

Я должен признать, что я не совсем уверен, чего вы пытаетесь достичь, написав свой класс-оболочку в 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 # или есть причина, которая запрещает это?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...