Hi Gustavo,
2017-08-28 0:18 GMT+09:00 Gustavo Sverzut Barbieri <[email protected]>:
> Hi all,
>
> q66 did a nice work to implement function pointers in Eolian, when you
> write this:
>
(Wasn't it Lauro Maura?)
function Function_Name {
> params {
> a: int;
> }
> return: bool;
> }
>
> you can then use your method as:
>
> method_name {
> params {
> cb: Function_Name
> }
> }
>
> Which results in:
>
> my_class_method(o, func_data, func, free_func);
>
> Basically enforces the pattern we always use, which is good. But
> keeping them explicitly as 3 pointers is a bit cumbersome.
>
> So my suggestion is to pack them in a structure, so it will become a
> single parameter (as would be exposed in higher level languages):
>
> typedef struct _Function_Name_Desc {
> Function_Name func;
> const void *data;
> Eina_Free_Cb free;
> } Function_Name_Desc;
>
> my_class_method(o, func_desc);
>
> A simple macro can make it more usable:
>
> #define FUNCTION_NAME(...) (Function_Name_Desc){__VA_ARGS}
>
> my_class_method(o, FUNCTION_NAME(func));
> my_class_method(o, FUNCTION_NAME(func, func_data));
> my_class_method(o, FUNCTION_NAME(func, func_data, free));
>
> and also named parameters:
>
> my_class_method(o, FUNCTION_NAME(.func = cb, .free = data_free));
>
> For method implementors it will be also simple, since we always have
> to do something like:
>
> struct _My_Class_Data {
> ...
> Function_Name func;
> const void *func_data;
> Eina_Free_Cb func_free;
> ...
> };
>
> pd->func = func;
> pd->func_data = func_data;
> pd->func_free = func_free;
>
> would become a simple entry:
>
> struct _My_Class_Data {
> ...
> Function_Name_Desc cb;
> ...
> };
>
> pd->cb = func_desc;
>
>
> And we could generate a caller macro:
>
> #define FUNCTION_NAME_CALL(desc, ...) \
> do { \
> if ((desc)->func) (desc)->func((void *)(desc)->data, ##
> __VA_ARGS); \
> } while (0)
>
> #define FUNCTION_NAME_CALL_RET(desc, ret_storage ...) \
> do { \
> if ((desc)->func) ret_storage = (desc)->func((void
> *)(desc)->data, ## __VA_ARGS); \
> } while (0)
>
> #define FUNCTION_NAME_FREE(desc) \
> do { \
> if ((desc)->free) (desc)->free((void *)(desc)->data); \
> (desc)->func = NULL; \
> (desc)->data = NULL; \
> (desc)->free = NULL; \
> } while (0)
>
> Then I could use in my object code:
>
>
> _my_class_func_caller(Eo *o, _My_Class_Data *pd, int a) {
> Eina_Bool r;
>
> FUNCTION_NAME_CALL_RET(&pd->cb, r, a);
> FUNCTION_NAME_FREE(&pd->cb); // won't be used anymore
> }
>
> What do you think?
>
>
As I've introduced the first usage of function pointers in EO I kept
thinking this needs to be standardized in a structure with proper macros.
Otherwise I'm sure we will end up with too many places that forget to free
the user data.
In fact we need a macro like stringshare_replace, which frees the previous
data.
I am not a fan of the call macros though, very ugly (their only value is
the NULL check).
--
Jean-Philippe André
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel