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 | + | {{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 | + | This page details how to convert between löve objects and [http://luajit.org/ext_ffi.html 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. | |
− | |||
− | |||
− | 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 == | ||
− | + | 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 | ||
− | + | return conv | |
− | + | ''' |
Revision as of 15:05, 1 November 2016
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
Contents
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