Запросите тип Lua userdata от C

Это ошибка в плагине, которая отмечена в разделе вопросов в Github

плагина. И есть обходной путь, который добавил один парень, но я не уверен, что это будет работать для вас, как показано здесь , то, что он сделал, было

CircleView.cs

Примечание: Комментарий Комментарий свойства CornerRadius.

    public class CircleView : BoxView
{
    //public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(nameof(CornerRadius), typeof(double), typeof(CircleView), 0.0);
    //public double CornerRadius
    //{
    //    get { return (double)GetValue(CornerRadiusProperty); }
    //    set { SetValue(CornerRadiusProperty, value); }
    //}
}

Для Android:

CircleViewRenderer.cs

Примечание. Добавлено жестко заданное значение для CornerRadius (16)

]

public class CircleViewRenderer : BoxRenderer
{
    private float _cornerRadius;
    private RectF _bounds;
    private Path _path;
    public CircleViewRenderer(Context context)
       : base(context)
    {
    }
    public static void Initialize() { }
    protected override void OnElementChanged(ElementChangedEventArgs e)
    {
        base.OnElementChanged(e);

        if (Element == null)
        {
            return;
        }
        var element = (CircleView)Element;

        _cornerRadius = TypedValue.ApplyDimension(ComplexUnitType.Dip, (float)16, Context.Resources.DisplayMetrics);

    }

    protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
    {
        base.OnSizeChanged(w, h, oldw, oldh);
        if (w != oldw && h != oldh)
        {
            _bounds = new RectF(0, 0, w, h);
        }

        _path = new Path();
        _path.Reset();
        _path.AddRoundRect(_bounds, _cornerRadius, _cornerRadius, Path.Direction.Cw);
        _path.Close();
    }

    public override void Draw(Canvas canvas)
    {
        canvas.Save();
        canvas.ClipPath(_path);
        base.Draw(canvas);
        canvas.Restore();
    }
}

Для iOS: CircleViewRenderer.cs Примечание. Добавленное жестко закодированное значение для кода iOS CornerRadius (16) еще не тестировалось.

public class CircleViewRenderer : BoxRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs e)
   {
       base.OnElementChanged(e);

       if (Element == null)
           return;

       Layer.MasksToBounds = true;
       //Layer.CornerRadius = (float)((CircleView)Element).CornerRadius / 2.0f;
       Layer.CornerRadius = (float)(16) / 2.0f;
   }
}

6
задан andygeers 7 April 2009 в 18:13
поделиться

4 ответа

Вы будете использовать lua_getmetatable и lua_equal для проверки того, что таблицы одинаковы.

По моему мнению, Луа должен оказать большую поддержку этому типу вещей, расширяющих тип. На данный момент ответственность за это лежит на системе-оболочке Lua / C (++).

В недавно созданной оболочке (в рамках коммерческого проекта) я делаю класс : : instance (L, index) , чтобы получить указатели пользовательских данных определенного типа. Другими словами, этот метод проверяет, что это пользовательские данные и что метатабель также является правильным. Если нет, возвращается NULL.

Lua мог бы помочь во всем этом, если бы у metatable было стандартное поле для расширенной информации о типе (sa __ type ). Это можно использовать так, чтобы сама функция type () возвращала «userdata» , "ххх" (два значения, в настоящее время возвращается только одно). Это останется совместимым с большей частью текущего кода. Но это только гипотетически (если вы не сделаете пользовательский тип () и не реализуете его самостоятельно).

3
ответ дан 10 December 2019 в 00:44
поделиться

Пользовательские данные должны иметь метатабельный, так что хватай его; затем найдите нужное имя в реестре. Если два объекта идентичны, вы нашли искомый тип.

Вы можете отправить этот тип в коде C, но позвольте мне мягко предложить вместо этого указать поле метатаблицы. Функция, хранящаяся в metatable, должна выполнять эту работу, но если нет, то если вам абсолютно необходимо переключить в коде C, затем выбрать имя и использовать его для индексации в metatable, и присвойте каждому метатабиту небольшое целое число, которое вы можете включить.

meta1.decision = 1
meta2.decision = 2
meta3.decision = 3

, а затем в своем коде C

if (lua_getmetatable(L, 1)) {
  lua_getfield(L, -1, "decision");
  if (lua_isnumber(L, -1)) {
    switch ((int) lua_tonumber(L, -1)) {
       case 1: ... ; break;
       case 2: ... ; break;
       case 3: ... ; break;
    }
    return 0;
  }
}
return luaL_error(L, "Userdata was not one of the expected types");
2
ответ дан 10 December 2019 в 00:44
поделиться

Вы могли всегда хранить поле маркера в таблице метаданных со светом userdata, оценивают уникальный для Вашего модуля.

static const char *green_flavor = "green";
...
void my_setflavor(lua_State *L, void *flavor) {
  lua_pushlightuserdata(L,flavor);
  lua_pushlstring(L,"_flavor");
  lua_rawset(L,-3);
}

void my_isflavor(lua_State *L, void *flavor) {
  void *p = NULL;
  lua_pushlstring(L,"_flavor");
  lua_rawget(L,-2);
  p = lua_touserdata(L,-1);
  lua_pop(L,1);
  return p == flavor;
}

Затем можно использовать my_setflavor(L,&green_flavor) установить _flavor поле таблицы наверху стека, и my_isflavor(L,&red_flavor) протестировать _flavor поле таблицы наверху стека.

Используемый этот путь, _flavor поле может только взять стоимость, которая может быть создана кодом в модуле, который имеет символ green_flavor в объеме, и поиск поля и тестирование его значения только потребовали одного поиска по таблице кроме извлечения самой таблицы метаданных. Обратите внимание, что значение переменной green_flavor не имеет значения, так как только ее адрес на самом деле используется.

С несколькими отличными переменными разновидности, доступными для использования в качестве значений сигнальной метки, _flavor поле может использоваться для различения нескольких связанных таблиц метаданных.

Все это сказало, естественный вопрос, "почему делают это вообще?" В конце концов, таблица метаданных могла легко содержать всю информацию, это должно получить соответствующее поведение. Это может с готовностью содержать функции, а также данные, и те функции могут быть получены и вызваны от C, а также Lua.

5
ответ дан 10 December 2019 в 00:44
поделиться

Я только что посмотрел на исходный код к luaL_checkudata функция, и это в основном выбирает использование таблицы метаданных userdata объекта lua_getmetatable. Это затем выбирает данное имя типа от использования реестра lua_getfield, и делает a lua_rawequal звоните для сравнения их.

0
ответ дан 10 December 2019 в 00:44
поделиться