2016-07-22 60 views
1

所以我試圖製作一個模塊,動態檢測您是否使用Lua或LuaJIT並創建一個表或cstruct。既然你不能添加metatables carrays,我有一個名爲_m在我的結構數組。在FFI結構中索引數組struct

以下是相關代碼的一部分,我將鏈接到下面的Git回購。

local mat4  = {} 
local mat4_mt = {} 

-- Private constructor. 
local function new(m) 
    m = m or { 
     0, 0, 0, 0, 
     0, 0, 0, 0, 
     0, 0, 0, 0, 
     0, 0, 0, 0 
    } 
    m._m = m 
    return setmetatable(m, mat4_mt) 
end 

-- Do the check to see if JIT is enabled. If so use the optimized FFI structs. 
local status, ffi 
if type(jit) == "table" and jit.status() then 
    status, ffi = pcall(require, "ffi") 
    if status then 
     ffi.cdef "typedef struct { double _m[16]; } cpml_mat4;" 
     new = ffi.typeof("cpml_mat4") 
    end 
end 

function mat4.transpose(out, a) 
    out[1] = a[1] 
    out[2] = a[5] 
    out[3] = a[9] 
    out[4] = a[13] 
    out[5] = a[2] 
    out[6] = a[6] 
    out[7] = a[10] 
    out[8] = a[14] 
    out[9] = a[3] 
    out[10] = a[7] 
    out[11] = a[11] 
    out[12] = a[15] 
    out[13] = a[4] 
    out[14] = a[8] 
    out[15] = a[12] 
    out[16] = a[16] 

    return out 
end 

mat4_mt.__index = function(t, k) 
    if type(t) == "cdata" then 
     if type(k) == "number" then 
      return t._m[k-1] 
     end 
    elseif type(k) == "number" then 
     return t._m[k] 
    end 

    return rawget(mat4, k) 
end 

function mat4_mt.__call(_, a) 
    return new(a) 
end 

if status then 
    ffi.metatype(new, mat4_mt) 
end 

return setmetatable({}, mat4_mt) 

這裏的問題是,當我嘗試調用轉,我收到以下錯誤:

'struct 173' cannot be indexed with 'number'

如果你看看mat4_mt.__index,我試圖檢測哪種類型的,我的工作with,table或cdata,並在結構中索引數組。

local mat4 = require "mat4" 
local a = mat4() 
local b = mat4():transpose(a) -- Error! 

的想法是,當您嘗試訪問,比如說,a[4],應該訪問a._m[3]在幕後,但是這顯然沒有發生,我不知道爲什麼。

想法?

https://github.com/excessive/cpml/blob/refactor/modules/mat4.lua

+0

上述代碼無法按所述方式工作。我必須用'return new(a或{})'替換'return new(a)'。鏈接不再有效。我在搜索錯誤消息時發現了這一點,所以也許答案仍然很有價值。 –

回答

0

它的工作,但你缺一__newindex元表項,造成out[index] = value失敗,因爲它仍然試圖索引結構,而不是它包含的領域。添加此問題可解決問題:

mat4_mt.__newindex = function(t, k, v) 
    if type(t) == "cdata" then 
     if type(k) == "number" then 
      t._m[k-1] = v 
     end 
    elseif type(k) == "number" then 
     t._m[k] = v 
    else 
     rawset(t, k, v) 
    end 
end