2016-07-22 25 views
1

Also ich versuche, ein Modul zu machen, das dynamisch erkennt, wenn Sie Lua oder LuaJIT verwenden und eine Tabelle oder ein cstruct abhängig erstellen. Da Sie keine Metatabellen zu Carrays hinzufügen können, habe ich ein Array namens _m in meiner Struktur.Indizieren Sie ein Array innerhalb einer FFI-Struktur

Hier ist ein Ausschnitt des entsprechenden Codes, ich werde auf den Git Repo unten verlinken.

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) 

Das Problem hier ist, dass, wenn ich umsetzen zu nennen versuchen, ich die folgende Fehlermeldung erhalten:

'struct 173' cannot be indexed with 'number'

Wenn Sie überprüfen mat4_mt.__index, ich, welche Art zu erfassen versucht bin, arbeite ich with, table oder cdata, und indiziert das Array innerhalb der Struktur.

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

Die Idee ist, dass, wenn Sie versuchen, zuzugreifen, sagen wir, a[4], sollte es a._m[3] hinter den Kulissen zugreifen, aber das ist eindeutig nicht der Fall, und ich habe keine Ahnung, warum.

Gedanken?

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

+0

Der obige Code funktioniert nicht wie angegeben. Ich musste 'return new (a)' durch 'return new (a oder {})' ersetzen. Der Link ist nicht mehr gültig. Ich habe dies gefunden, während ich nach der Fehlermeldung gesucht habe, also ist eine Antwort vielleicht immer noch wertvoll. –

Antwort

0

Es funktioniert, aber Ihnen fehlt ein __newindex Metatabelle Eintrag, out[index] = value verursacht zu scheitern, weil es die Struktur zu indizieren noch versucht, anstatt das Feld enthält. Das Hinzufügen dieses Problems behebt das Problem:

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