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

m (some fixes, inlined code, edited so it keeps to its own namespace, fixed function formatting.)
Line 1: Line 1:
{{notice|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 is going erase the original userdata at any time.}}
+
{{notice|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 leads to conversion between löve objects and FFI (Foreign Function Interface) structures.
+
This page details how to convert between löve objects and [http://luajit.org/ext_ffi.html FFI] (Foreign Function Interface) structures.
  
* If you don't know what FFI is, check http://luajit.org/ext_ffi.html
+
Love objects in lua are always stored in a userdata object (Proxy) that contains the object itself, and a type identifier.
* Download the code from here http://pastebin.com/Ad9dPKiZ
 
 
 
Love objects in lua are always stored in a userdata object (Proxy) that contains the object itself and a type identifier.
 
 
* Check the line 99 to see the structure of the Proxy object
 
* Check the line 99 to see the structure of the Proxy object
  
 
== Functions ==
 
== Functions ==
<i>cdata</i> Object, <i>number</i> Type, <i>string</i> TypeName = <b>love.ffi</b>(<i>Object</i> Object)<br>
+
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.
Description: 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 ===
 +
<source lang="lua">
 +
Pointer, Type, TypeEnum = objectToPointer( Object )
 +
</source>
 +
=== Arguments ===
 +
{{param|Object|Object|The LÖVE type superclass.}}
 +
=== Returns ===
 +
{{param|cdata|Pointer|An FFI pointer containing the object's location.}}
 +
{{param|string|Type|The LÖVE object's type.}}
 +
{{param|number|TypeEnum|The LÖVE object's type as an enumeration value.}}
 +
 
 +
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 ===
 +
<source lang="lua">
 +
Object = pointerToObject( Pointer, Type, TypeEnum )
 +
</source>
 +
=== Arguments ===
 +
{{param|cdata|Pointer|An FFI pointer containing the object's location.}}
 +
{{param|string|Type|The LÖVE object's type.}}
 +
{{param|number|TypeEnum|The LÖVE object's type as an enumeration value.}}
 +
=== Returns ===
 +
{{param|Object|Object|The LÖVE type superclass.}}
 +
 
 +
== 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
  
<i>Object</i> Object = <b>love.fromffi</b>(<i>cdata</i> Object, <i>number</i> Type, <i>string</i> TypeName)<br>
+
return conv
Description: 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.
+
'''

Revision as of 15:05, 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.

  • Check the line 99 to see the structure of the Proxy object

Functions

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
The LÖVE type superclass.

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.

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
The LÖVE type superclass.

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