eo: add an API entry for custom instantiation of Eo objects for binding usage

Add a new function in the Eo API in order to provide more options on object
instantiation for binding creators.

For the Eo lib to be able to construct objects that inherit from bindings in
many languages we should provide a way for bindings to call different kinds of
constructors, in a way that simply overriding the `efl_constructor` method is
not enough.
We need a way to differentiate at construction time if the Eo is being
constructed from C or from the binding, because if it is the
former we need too call the inherited object constructor from C and instantiate
a new object, and if it is the later we need to avoid instantiating a
new object because we are already in the middle of the process of creating
a new one.
`efl_constructor` alone does not provide any way of distinguishing between
those situations, so, being able to pass additional information for
efl_add_start (like a custom constructor pointer) is necessary to make the
right distinction.

Reviewed-by: Cedric BAIL <cedric.bail@free.fr>
Differential Revision: https://phab.enlightenment.org/D9070
This commit is contained in:
Vitor Sousa 2019-06-04 22:39:51 +00:00 committed by Cedric BAIL
parent 673bce2b91
commit fb7f9d4ed3
2 changed files with 44 additions and 3 deletions

View File

@ -1539,6 +1539,35 @@ EAPI Eo *_efl_added_get(void);
EAPI Eo * _efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, Eo *parent, Eina_Bool ref, Eina_Bool is_fallback);
/**
* @typedef Efl_Substitute_Ctor_Cb
* Callback to be called instead of the object constructor.
*
* Only intended for binding creators.
*
* @param data Additional data previously supplied by the user
* @param obj_id The object being constructed.
* @return The constructed object in case of success, NULL otherwise.
*/
typedef Eo *(*Efl_Substitute_Ctor_Cb)(void *data, Eo *obj_id);
/**
* @brief Just like _efl_add_internal_start() but with additional options
*
* Only intended for binding creators.
*
* @param file File name of the call site, used for debug logs.
* @param line Line number of the call site, used for debug logs.
* @param klass_id Pointer for the class being instantiated.
* @param ref Whether or not the object will have an additional reference if it has a parent.
* @param parent Object parent, can be NULL.
* @param is_fallback Whether or not the fallback @c efl_added behaviour is to be used.
* @param substitute_ctor Optional callback to replace the call for efl_constructor(), if NULL efl_constructor() will be called normally.
* @param sub_ctor_data Additional data to be passed to the @p substitute_ctor callback.
* @return An handle to the new object on success, NULL otherwise.
*/
EAPI Eo * _efl_add_internal_start_bindings(const char *file, int line, const Efl_Class *klass_id, Eo *parent, Eina_Bool ref, Eina_Bool is_fallback, Efl_Substitute_Ctor_Cb substitute_ctor, void *sub_ctor_data);
/**
* @brief Unrefs the object and reparents it to NULL.
*

View File

@ -857,8 +857,8 @@ err_klass:
return EINA_FALSE;
}
EAPI Eo *
_efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, Eo *parent_id, Eina_Bool ref, Eina_Bool is_fallback)
static Eo *
_efl_add_internal_start_do(const char *file, int line, const Efl_Class *klass_id, Eo *parent_id, Eina_Bool ref, Eina_Bool is_fallback, Efl_Substitute_Ctor_Cb substitute_ctor, void *sub_ctor_data)
{
const char *func_name = __FUNCTION__;
_Eo_Object *obj;
@ -918,7 +918,8 @@ _efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, E
if (parent_id) efl_parent_set(eo_id, parent_id);
/* eo_id can change here. Freeing is done on the resolved object. */
eo_id = efl_constructor(eo_id);
if (!substitute_ctor) eo_id = efl_constructor(eo_id);
else eo_id = substitute_ctor(sub_ctor_data, eo_id);
// not likely so use goto to alleviate l1 instruction cache of rare code
if (!eo_id) goto err_noid;
// not likely so use goto to alleviate l1 instruction cache of rare code
@ -962,6 +963,17 @@ err_parent:
return NULL;
}
EAPI Eo *
_efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, Eo *parent_id, Eina_Bool ref, Eina_Bool is_fallback)
{
return _efl_add_internal_start_do(file, line, klass_id, parent_id, ref, is_fallback, NULL, NULL);
}
EAPI Eo * _efl_add_internal_start_bindings(const char *file, int line, const Efl_Class *klass_id, Eo *parent_id, Eina_Bool ref, Eina_Bool is_fallback, Efl_Substitute_Ctor_Cb substitute_ctor, void *sub_ctor_data)
{
return _efl_add_internal_start_do(file, line, klass_id, parent_id, ref, is_fallback, substitute_ctor, sub_ctor_data);
}
static Eo *
_efl_add_internal_end(Eo *eo_id, Eo *finalized_id)
{