Conversion between love objects and FFI structures

This page details how to convert between löve objects and FFI (Foreign Function Interface) structures.

Love objects in lua are stored in a userdata object (Proxy) that contains the object itself, and a type identifier. See the code below for details.

O.png This is NOT recommended for anyone to use. It will break at any time. The only non-breaking conversion between love objects and FFI data is via Data:getPointer, which you can cast to a FFI pointer via ffi.cast. The garbage collector may erase the original userdata at any time.  


O.png This only applies to version 0.10.0. Subsequent versions may break this at any time. You have been warned.  



Function

This function converts a love object into a FFI cdata object. It returns the object itself (not the Proxy object), it's type and type name.

Synopsis

Pointer, Type, TypeEnum = objectToPointer( Object )

Arguments

Object Object
A LÖVE object.

Returns

cdata Pointer
An FFI pointer containing the object's location.
string Type
The LÖVE object's type.
number TypeEnum
The LÖVE object's type as an enumeration value.

Function

This function converts a FFI cdata object into a Proxy userdata object, it is required to give the type name to assign the metatable to the userdata object, and the type id for the Proxy object.

Synopsis

Object = pointerToObject( Pointer, Type, TypeEnum )

Arguments

cdata Pointer
An FFI pointer containing the object's location.
string Type
The LÖVE object's type.
number TypeEnum
The LÖVE object's type as an enumeration value.

Returns

Object Object
A LÖVE object.

Code

ffi = require("ffi")
 
ffi.cdef [[
    typedef enum  {
        INVALID_ID = 0,
        OBJECT_ID,
        DATA_ID,
        MODULE_ID,
        STREAM_ID,
 
        // Filesystem.
        FILESYSTEM_FILE_ID,
        FILESYSTEM_DROPPED_FILE_ID,
        FILESYSTEM_FILE_DATA_ID,
 
        // Font
        FONT_GLYPH_DATA_ID,
        FONT_RASTERIZER_ID,
 
        // Graphics
        GRAPHICS_DRAWABLE_ID,
        GRAPHICS_TEXTURE_ID,
        GRAPHICS_IMAGE_ID,
        GRAPHICS_QUAD_ID,
        GRAPHICS_FONT_ID,
        GRAPHICS_PARTICLE_SYSTEM_ID,
        GRAPHICS_SPRITE_BATCH_ID,
        GRAPHICS_CANVAS_ID,
        GRAPHICS_SHADER_ID,
        GRAPHICS_MESH_ID,
        GRAPHICS_TEXT_ID,
        GRAPHICS_VIDEO_ID,
 
        // Image
        IMAGE_IMAGE_DATA_ID,
        IMAGE_COMPRESSED_IMAGE_DATA_ID,
 
        // Joystick
        JOYSTICK_JOYSTICK_ID,
 
        // Math
        MATH_RANDOM_GENERATOR_ID,
        MATH_BEZIER_CURVE_ID,
        MATH_COMPRESSED_DATA_ID,
 
        // Audio
        AUDIO_SOURCE_ID,
 
        // Sound
        SOUND_SOUND_DATA_ID,
        SOUND_DECODER_ID,
 
        // Mouse
        MOUSE_CURSOR_ID,
 
        // Physics
        PHYSICS_WORLD_ID,
        PHYSICS_CONTACT_ID,
        PHYSICS_BODY_ID,
        PHYSICS_FIXTURE_ID,
        PHYSICS_SHAPE_ID,
        PHYSICS_CIRCLE_SHAPE_ID,
        PHYSICS_POLYGON_SHAPE_ID,
        PHYSICS_EDGE_SHAPE_ID,
        PHYSICS_CHAIN_SHAPE_ID,
        PHYSICS_JOINT_ID,
        PHYSICS_MOUSE_JOINT_ID,
        PHYSICS_DISTANCE_JOINT_ID,
        PHYSICS_PRISMATIC_JOINT_ID,
        PHYSICS_REVOLUTE_JOINT_ID,
        PHYSICS_PULLEY_JOINT_ID,
        PHYSICS_GEAR_JOINT_ID,
        PHYSICS_FRICTION_JOINT_ID,
        PHYSICS_WELD_JOINT_ID,
        PHYSICS_ROPE_JOINT_ID,
        PHYSICS_WHEEL_JOINT_ID,
        PHYSICS_MOTOR_JOINT_ID,
 
        // Thread
        THREAD_THREAD_ID,
        THREAD_CHANNEL_ID,
 
        // Video
        VIDEO_VIDEO_STREAM_ID,
 
        // The modules themselves. Only add abstracted modules here.
        MODULE_FILESYSTEM_ID,
        MODULE_GRAPHICS_ID,
        MODULE_IMAGE_ID,
        MODULE_SOUND_ID,
 
        // Count the number of bits needed.
        TYPE_MAX_ENUM
    } Type;
   
    typedef struct Object {
    } Object;
   
    typedef struct Proxy {
        Type type;
        Object * object;
    };
]]

local conv = {}

function conv.objectToPointer(Object)
    local Proxy = ffi.cast("Proxy *", Object)
    return Proxy.object, tonumber(Proxy.type), Object:type()
end
 
function conv.pointerToObject(CData, Type, TypeName)
    local Object = newproxy(true)
    local Metatable = debug.getregistry()[TypeName]
    debug.setmetatable(Object, Metatable)
   
    local Proxy = ffi.cast("Proxy *", Object)
    Proxy.type = Type
    Proxy.object = CData
   
    return Object
end

return conv

Other Languages