Difference between revisions of "Conversion between love objects and FFI structures"

(Meant no malice with my last commit, accidentally left in the minor edit flag. This'll be a major edit to compensate.)
m (Code)
Line 158: Line 158:
  
 
return conv
 
return conv
'''
 

Revision as of 18:06, 1 November 2016

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.  


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

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

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

<source lang="lua"> 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