Маршрутизация параметров конструктора luajit ffi

Пример в разделе руководства: "Определение метаметодов для типа C" выглядит следующим образом:

local ffi = require("ffi")
ffi.cdef[[
typedef struct { double x, y; } point_t;
]]

local point
local mt = {
  __add = function(a, b) return point(a.x+b.x, a.y+b.y) end,
  __len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end,
  __index = {
    area = function(a) return a.x*a.x + a.y*a.y end,
  },
}
point = ffi.metatype("point_t", mt)

local a = point(3, 4)

Я немного смущен тем, где находится «конструктор», я предполагаю, что по умолчанию point(3,4) - это неявная маршрутизация 3 -> x и 5 -> y. Как насчет того, когда я хочу повесить некоторую логику на конструктор? Иными словами. Как указать конструктор не по умолчанию?

Я оборачиваю кучу c-библиотек в объектно-ориентированный код lua, и меня не волнует переносимость на канонический lua. В частности, мне нужно подключить три основные функции объектно-ориентированного программирования для управления временем жизни объекта: create, init, destroy. Я знаю, что уничтожение будет __gc методом моих типов metatable. Поэтому мне нужно знать, как выполнять create и init, и, надеюсь, избежать инициализации по умолчанию, выполняемой luajit.

изменить

ffi.new и другие имеют множество правил, регулирующих создание типов (задокументировано на странице семантики luajit ffi). это в разделе семантики. Я все еще хотел бы знать, каким самым чистым способом было бы повесить пользовательских создателей и инициализаторов (которые входят в состав библиотеки c) в создание объекта ffi.


person Hassan Syed    schedule 21.02.2012    source источник


Ответы (1)


Вам нужно будет обернуть вызов point, чтобы получить желаемое:

local function newpoint ( vals )
    -- Do stuff with vals here?
    return point ( vals )
end
newpoint {x=5;y=4}

ИЛИ вы можете рассматривать свою точечную функцию как функцию создания; и просто есть метод инициализации...

mt.__index.init = function ( p , x , y )
     p.x = x;
     p.y = y;
end

local mypoint = point()
mypoint:init ( 1 , 2 )

Примечание; ко всем объектам типа точки уже применена ваша метатаблица, поэтому вам не нужно прикреплять методы или что-то еще.

Мне это кажется немного бессмысленным.... почему вы хотите разделить создание и инициализацию??

person daurnimator    schedule 21.02.2012
comment
Ха-ха-ха, да, бессмысленно, это продолжало крутиться у меня в голове. Это класс, который создает объекты BSON/JSON. Существует метод init для сброса класса после создания документа. Затем есть malloc/free create destroy. будучи программистом C -> C++ -> lua, я получил оленя в фаре :D - person Hassan Syed; 22.02.2012
comment
Небольшое полезное дополнение: сделайте так, чтобы метод init возвращал объект, к которому он был вызван, например: mt.__index.init = function(p,x,x)p.x,p.y=x,y return p end, чтобы вы могли сделать это: mypoint = point():init(1, 3). Не очень важно, но весьма удобно (цепочка может сделать код очень аккуратным). - person Deco; 22.02.2012
comment
Спасибо, деко, каждая идиома помогает :D - person Hassan Syed; 22.02.2012