Re: Callback Wrapping Help
- Posted by ghaberek (admin) Mar 15, 2023
- 782 views
Hello all,
I am having trouble wrapping my head around on how to wrap callbacks.
These are function pointer types (mostly use for callbacks, but there are other uses). The asterisk inside the parentheses is part of the type name (because it's a function pointer) not the return value.
typedef size_t (*sfShapeGetPointCountCallback)(void*); ///< Type of the callback used to get the number of points in a shape typedef sfVector2f (*sfShapeGetPointCallback)(size_t, void*); ///< Type of the callback used to get a point of a shape
This function declaration uses the function pointer types above to take function pointers as a parameter, which it can then use to call that function (hence "callback").
CSFML_GRAPHICS_API sfShape* sfShape_create(sfShapeGetPointCountCallback getPointCount, sfShapeGetPointCallback getPoint, void* userData);
First we need to declare sfVector2f struct so FFI knows how to correctly return the value from sfShapeGetPointCallback().
typedef struct { float x; float y; } sfVector2f;
constant SF_VECTOR2F = define_c_struct({ C_FLOAT, -- x C_FLOAT -- y })
The we need to declare our own functions that accept the parameters in the typedef's above. I had to dig into the ShapeStruct header to figure out the parameter names and I found some examples demonstrating how to implement custom shapes.
-- Our custom shape data (we can use userData parameter as a shape id). -- You could use this approach to define any number of custom shapes. sequence sfShapes = { {{-10.0,-10.0},{10.0,-10.0},{10.0,10.0},{-10.0,10.0}} -- a square } constant SHAPE_SQUARE = 1 -- shape id of the square above -- Callback that provides the point count of the shape function sfShapeGetPointCountCallback( atom userData ) atom shapeId = userData -- should be 1 (SHAPE_SQUARE) return length( sfShapes[shapeId] ) -- should return 4 end function -- Declare the call back with its parameter and return types constant sfShapeGetPointCountCallback_cb = call_back( routine_id("sfShapeGetPointCountCallback"), {C_POINTER}, C_SIZE_T ) -- Callback that provides the points of the shape function sfShapeGetPointCallback( atom index, atom userData ) atom shapeId = userData -- should be 1 atom x = sfShapes[shapeId][1] atom y = sfShapes[shapeId][2] return {x,y} -- should return two floats (struct sfVector2f) end function -- Declare the call back with its parameter and return types constant sfShapeGetPointCallback_cb = call_back( routine_id("sfShapeGetPointCallback"), {C_SIZE_T,C_POINTER}, SF_VECTOR2F )
Then we declare the the function as you did.
constant C_CALLBACK = C_POINTER -- I'm going to add this to std/ffi.e so we can distinguish callbacks from other pointers constant xsfShape_create = define_c_func(gfx,"+sfShape_create",{C_CALLBACK,C_CALLBACK,C_POINTER},C_POINTER) public function sfShape_create(atom getPointCount, atom getPoint, atom userData) return c_func(xsfShape_create,{getPointCount,getPoint,userData}) end function
Finally, we would call it like this:
atom shape = sfShape_create( sfShapeGetPointCountCallback_cb, sfShapeGetPointCallback_cb, SHAPE_SQUARE )
-Greg