forked from enlightenment/efl
eolian: function pointers
First steps toward explicit function pointer support in eolian. To declare a function pointer type, use the following syntax, similar to a regular eolian method declaration. function FunctionName { params { ... } return: Return type }
This commit is contained in:
parent
0fcee227aa
commit
1634c14169
|
@ -128,9 +128,30 @@ _gen_func(const Eolian_Unit *src, const Eolian_Function *fid,
|
|||
EINA_ITERATOR_FOREACH(itr, pr)
|
||||
{
|
||||
const Eolian_Type *prt = eolian_parameter_type_get(pr);
|
||||
const Eolian_Typedecl *ptd = eolian_type_typedecl_get(prt);
|
||||
const char *prn = eolian_parameter_name_get(pr);
|
||||
Eina_Stringshare *prtn = eolian_type_c_type_get(prt);
|
||||
|
||||
if (ptd && eolian_typedecl_type_get(ptd) == EOLIAN_TYPEDECL_FUNCTION_POINTER)
|
||||
{
|
||||
nidx += 3;
|
||||
if (!first)
|
||||
eina_strbuf_append(buf, ", ");
|
||||
eina_strbuf_append_printf(buf, "void *%s_data, %s %s, Eina_Free_Cb %s_free_cb",
|
||||
prn, prtn, prn, prn);
|
||||
eina_stringshare_del(prtn);
|
||||
if (!eolian_parameter_is_nonull(pr))
|
||||
continue;
|
||||
if (!flagbuf)
|
||||
{
|
||||
flagbuf = eina_strbuf_new();
|
||||
eina_strbuf_append_printf(flagbuf, " EINA_ARG_NONNULL(%d", nidx - 1);
|
||||
}
|
||||
else
|
||||
eina_strbuf_append_printf(flagbuf, ", %d", nidx - 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
++nidx;
|
||||
if (!first)
|
||||
eina_strbuf_append(buf, ", ");
|
||||
|
|
|
@ -68,6 +68,40 @@ _type_exists(const char *tname, Eina_Strbuf *buf)
|
|||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_gen_func_pointer_param(const char *name, Eina_Stringshare *c_type,
|
||||
const Eolian_Typedecl *typedecl EINA_UNUSED,
|
||||
Eina_Strbuf *params, Eina_Strbuf *params_full,
|
||||
Eina_Strbuf *params_full_imp,
|
||||
Eina_Bool is_empty EINA_UNUSED)
|
||||
{
|
||||
Eina_Strbuf *dataname = eina_strbuf_new();
|
||||
Eina_Strbuf *freename = eina_strbuf_new();
|
||||
|
||||
eina_strbuf_append_printf(dataname, "%s_data", name);
|
||||
eina_strbuf_append_printf(freename, "%s_free_cb", name);
|
||||
|
||||
if (eina_strbuf_length_get(params))
|
||||
eina_strbuf_append(params, ", ");
|
||||
|
||||
eina_strbuf_append_printf(params, "%s, %s, %s",
|
||||
eina_strbuf_string_get(dataname),
|
||||
name,
|
||||
eina_strbuf_string_get(freename));
|
||||
|
||||
eina_strbuf_append_printf(params_full_imp, ", void *%s, %s %s, Eina_Free_Cb %s",
|
||||
eina_strbuf_string_get(dataname),
|
||||
c_type, name,
|
||||
eina_strbuf_string_get(freename));
|
||||
eina_strbuf_append_printf(params_full, ", void *%s, %s %s, Eina_Free_Cb %s",
|
||||
eina_strbuf_string_get(dataname),
|
||||
c_type, name,
|
||||
eina_strbuf_string_get(freename));
|
||||
|
||||
eina_strbuf_free(dataname);
|
||||
eina_strbuf_free(freename);
|
||||
}
|
||||
|
||||
static void
|
||||
_append_defval(const Eolian_Unit *src, Eina_Strbuf *buf,
|
||||
const Eolian_Expression *exp, const Eolian_Type *tp)
|
||||
|
@ -212,10 +246,18 @@ _gen_func(const Eolian_Unit *src, const Eolian_Class *cl,
|
|||
const char *prn = eolian_parameter_name_get(pr);
|
||||
const Eolian_Type *pt = eolian_parameter_type_get(pr);
|
||||
Eina_Stringshare *ptn = eolian_type_c_type_get(pt);
|
||||
const Eolian_Typedecl *ptd = eolian_type_typedecl_get(pt);
|
||||
|
||||
Eina_Bool had_star = ptn[strlen(ptn) - 1] == '*';
|
||||
const char *add_star = _get_add_star(ftype, pd);
|
||||
|
||||
if (ptd && eolian_typedecl_type_get(ptd) == EOLIAN_TYPEDECL_FUNCTION_POINTER)
|
||||
{
|
||||
_gen_func_pointer_param(prn, ptn, ptd, params, params_full, params_full_imp, is_empty);
|
||||
eina_stringshare_del(ptn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (eina_strbuf_length_get(params))
|
||||
eina_strbuf_append(params, ", ");
|
||||
|
||||
|
@ -828,8 +870,18 @@ _gen_params(const Eolian_Function *fid, Eolian_Function_Type ftype,
|
|||
Eolian_Parameter_Dir pd = eolian_parameter_direction_get(pr);
|
||||
const char *prn = eolian_parameter_name_get(pr);
|
||||
const Eolian_Type *pt = eolian_parameter_type_get(pr);
|
||||
const Eolian_Typedecl *ptd = eolian_type_typedecl_get(pt);
|
||||
Eina_Stringshare *ptn = eolian_type_c_type_get(pt);
|
||||
|
||||
if (ptd && eolian_typedecl_type_get(ptd) == EOLIAN_TYPEDECL_FUNCTION_POINTER)
|
||||
{
|
||||
eina_strbuf_append_printf(params, ", %s_data, %s, %s_free_cb", prn, prn, prn);
|
||||
eina_strbuf_append_printf(params_full, ", void *%s_data, %s %s, Eina_Free_Cb %s_free_cb", prn, ptn, prn, prn);
|
||||
|
||||
eina_stringshare_del(ptn);
|
||||
continue;
|
||||
}
|
||||
|
||||
Eina_Bool had_star = ptn[strlen(ptn) - 1] == '*';
|
||||
const char *add_star = _get_add_star(ftype, pd);
|
||||
|
||||
|
|
|
@ -131,6 +131,51 @@ _type_generate(const Eolian_Unit *src, const Eolian_Typedecl *tp,
|
|||
char *fn = eo_gen_c_full_name_get(eolian_typedecl_full_name_get(tp));
|
||||
eina_strbuf_append_printf(buf, "} %s", fn);
|
||||
free(fn);
|
||||
break;
|
||||
}
|
||||
case EOLIAN_TYPEDECL_FUNCTION_POINTER:
|
||||
{
|
||||
const Eolian_Function *fid = eolian_typedecl_function_pointer_get(tp);
|
||||
|
||||
eina_strbuf_append(buf, "typedef ");
|
||||
|
||||
/* Return type */
|
||||
const Eolian_Type *rtp = eolian_function_return_type_get(fid, EOLIAN_FUNCTION_POINTER);
|
||||
if (!rtp)
|
||||
eina_strbuf_append(buf, "void ");
|
||||
else
|
||||
{
|
||||
Eina_Stringshare *ct = eolian_type_c_type_get(rtp);
|
||||
eina_strbuf_append_printf(buf, "%s ", ct);
|
||||
}
|
||||
|
||||
/* Function name */
|
||||
char *fn = eo_gen_c_full_name_get(eolian_typedecl_full_name_get(tp));
|
||||
eina_strbuf_append_printf(buf, "(*%s)", fn);
|
||||
free(fn);
|
||||
|
||||
/* Parameters */
|
||||
eina_strbuf_append(buf, "(void *data");
|
||||
Eina_Iterator *params = eolian_function_parameters_get(fid);
|
||||
const Eolian_Function_Parameter *param = NULL;
|
||||
EINA_ITERATOR_FOREACH(params, param)
|
||||
{
|
||||
const Eolian_Typedecl *ptd = eolian_type_typedecl_get(eolian_parameter_type_get(param));
|
||||
Eina_Stringshare *pn = eolian_parameter_name_get(param);
|
||||
Eina_Stringshare *pt = eolian_type_c_type_get(eolian_parameter_type_get(param));
|
||||
|
||||
if (!pn)
|
||||
pn = ""; // FIXME add some kind of param1/param2 control for null?
|
||||
|
||||
if (ptd && eolian_typedecl_type_get(ptd) == EOLIAN_TYPEDECL_FUNCTION_POINTER)
|
||||
eina_strbuf_append_printf(buf, ", void *%s_data, %s %s, Eina_Free_Cb %s_free_cb",
|
||||
pn, pt, pn, pn);
|
||||
else
|
||||
eina_strbuf_append_printf(buf, ", %s %s", pt, pn);
|
||||
|
||||
}
|
||||
eina_strbuf_append(buf, ")");
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -183,7 +183,8 @@ typedef enum
|
|||
EOLIAN_PROPERTY,
|
||||
EOLIAN_PROP_SET,
|
||||
EOLIAN_PROP_GET,
|
||||
EOLIAN_METHOD
|
||||
EOLIAN_METHOD,
|
||||
EOLIAN_FUNCTION_POINTER
|
||||
} Eolian_Function_Type;
|
||||
|
||||
typedef enum
|
||||
|
@ -217,7 +218,8 @@ typedef enum
|
|||
EOLIAN_TYPEDECL_STRUCT,
|
||||
EOLIAN_TYPEDECL_STRUCT_OPAQUE,
|
||||
EOLIAN_TYPEDECL_ENUM,
|
||||
EOLIAN_TYPEDECL_ALIAS
|
||||
EOLIAN_TYPEDECL_ALIAS,
|
||||
EOLIAN_TYPEDECL_FUNCTION_POINTER
|
||||
} Eolian_Typedecl_Type;
|
||||
|
||||
typedef enum
|
||||
|
@ -820,6 +822,16 @@ EAPI Eina_Bool eolian_function_is_beta(const Eolian_Function *function_id);
|
|||
*/
|
||||
EAPI Eina_Bool eolian_function_is_constructor(const Eolian_Function *function_id, const Eolian_Class *klass);
|
||||
|
||||
/*
|
||||
* @brief Get whether a function is a function pointer.
|
||||
*
|
||||
* @param[in] function_id Id of the function
|
||||
* @return EINA_TRUE and EINA_FALSE respectively
|
||||
*
|
||||
* @ingroup Eolian
|
||||
*/
|
||||
EAPI Eina_Bool eolian_function_is_function_pointer(const Eolian_Function *function_id);
|
||||
|
||||
/*
|
||||
* @brief Returns an iterator to the parameter handles for a method/ctor/dtor.
|
||||
*
|
||||
|
@ -1730,6 +1742,16 @@ EAPI Eina_Iterator *eolian_typedecl_namespaces_get(const Eolian_Typedecl *tp);
|
|||
*/
|
||||
EAPI Eina_Stringshare *eolian_typedecl_free_func_get(const Eolian_Typedecl *tp);
|
||||
|
||||
/*
|
||||
* @breif Get the function object for this function pointer type.
|
||||
*
|
||||
* @param[in] tp the type.
|
||||
* @return the function or NULL;
|
||||
*
|
||||
* @ingroup Eolian
|
||||
*/
|
||||
EAPI const Eolian_Function *eolian_typedecl_function_pointer_get(const Eolian_Typedecl *tp);
|
||||
|
||||
/*
|
||||
* @brief Get the type of a type.
|
||||
*
|
||||
|
|
|
@ -102,6 +102,7 @@ eolian_function_full_c_name_get(const Eolian_Function *foo_id,
|
|||
case EOLIAN_METHOD:
|
||||
case EOLIAN_PROPERTY:
|
||||
case EOLIAN_PROP_GET:
|
||||
case EOLIAN_FUNCTION_POINTER:
|
||||
if (foo_id->get_legacy && use_legacy)
|
||||
{
|
||||
if (!strcmp(foo_id->get_legacy, "null"))
|
||||
|
@ -120,7 +121,7 @@ eolian_function_full_c_name_get(const Eolian_Function *foo_id,
|
|||
}
|
||||
|
||||
char tbuf[512];
|
||||
const char *prefix = _get_eo_prefix(foo_id, tbuf, use_legacy);
|
||||
const char *prefix = (ftype != EOLIAN_FUNCTION_POINTER) ? _get_eo_prefix(foo_id, tbuf, use_legacy): tbuf;
|
||||
|
||||
if (!prefix)
|
||||
return NULL;
|
||||
|
@ -278,7 +279,7 @@ EAPI Eina_Iterator *
|
|||
eolian_function_parameters_get(const Eolian_Function *fid)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fid, NULL);
|
||||
if (fid->type != EOLIAN_METHOD)
|
||||
if (fid->type != EOLIAN_METHOD && fid->type != EOLIAN_FUNCTION_POINTER)
|
||||
return NULL;
|
||||
return (fid->params ? eina_list_iterator_new(fid->params) : NULL);
|
||||
}
|
||||
|
@ -303,6 +304,8 @@ eolian_function_return_type_get(const Eolian_Function *fid, Eolian_Function_Type
|
|||
if ((fid->type != EOLIAN_PROP_SET) && (fid->type != EOLIAN_PROPERTY))
|
||||
return NULL;
|
||||
return fid->set_ret_type;
|
||||
case EOLIAN_FUNCTION_POINTER:
|
||||
return (fid->type != EOLIAN_FUNCTION_POINTER) ? NULL : fid->get_ret_type;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -437,3 +437,12 @@ eolian_typedecl_free_func_get(const Eolian_Typedecl *tp)
|
|||
EINA_SAFETY_ON_NULL_RETURN_VAL(tp, NULL);
|
||||
return tp->freefunc;
|
||||
}
|
||||
|
||||
EAPI const Eolian_Function *
|
||||
eolian_typedecl_function_pointer_get(EINA_UNUSED const Eolian_Typedecl *tp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(tp, NULL);
|
||||
if (eolian_typedecl_type_get(tp) != EOLIAN_TYPEDECL_FUNCTION_POINTER)
|
||||
return NULL;
|
||||
return tp->function_pointer;
|
||||
}
|
||||
|
|
|
@ -118,6 +118,9 @@ _validate_typedecl(const Eolian_Typedecl *tp)
|
|||
eina_hash_foreach(tp->fields, (Eina_Hash_Foreach)_ef_map_cb, &succ);
|
||||
return succ;
|
||||
}
|
||||
case EOLIAN_TYPEDECL_FUNCTION_POINTER:
|
||||
// FIXME validate functions here
|
||||
return EINA_TRUE;
|
||||
default:
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ static const char * const ctypes[] =
|
|||
"void *",
|
||||
|
||||
"Eina_Free_Cb",
|
||||
"function",
|
||||
};
|
||||
|
||||
#undef KW
|
||||
|
|
|
@ -58,6 +58,7 @@ enum Tokens
|
|||
\
|
||||
KW(void_ptr), \
|
||||
KW(__builtin_free_cb), \
|
||||
KW(function), \
|
||||
KW(__undefined_type), \
|
||||
\
|
||||
KW(true), KW(false), KW(null)
|
||||
|
|
|
@ -1406,6 +1406,108 @@ end:
|
|||
_func_pure_virtual_set(ls, prop, has_virtp);
|
||||
}
|
||||
|
||||
static Eolian_Typedecl*
|
||||
parse_function_pointer(Eo_Lexer *ls)
|
||||
{
|
||||
int line, col;
|
||||
Eolian_Typedecl *def = push_typedecl(ls);
|
||||
Eina_Strbuf *buf = push_strbuf(ls);
|
||||
Eolian_Function *meth = NULL;
|
||||
|
||||
Eina_Bool has_const = EINA_FALSE,
|
||||
has_params = EINA_FALSE,
|
||||
has_return = EINA_FALSE,
|
||||
has_c_only = EINA_FALSE,
|
||||
has_beta = EINA_FALSE;
|
||||
|
||||
eo_lexer_get(ls);
|
||||
parse_name(ls, buf);
|
||||
|
||||
def->type = EOLIAN_TYPEDECL_FUNCTION_POINTER;
|
||||
def->is_extern = EINA_FALSE;
|
||||
|
||||
FILL_BASE(def->base, ls, ls->line_number, ls->column);
|
||||
|
||||
_fill_name(eina_stringshare_add(eina_strbuf_string_get(buf)),
|
||||
&def->full_name, &def->name, &def->namespaces);
|
||||
|
||||
pop_strbuf(ls);
|
||||
|
||||
meth = calloc(1, sizeof(Eolian_Function));
|
||||
meth->klass = NULL;
|
||||
meth->type = EOLIAN_FUNCTION_POINTER;
|
||||
meth->get_scope = meth->set_scope = EOLIAN_SCOPE_PUBLIC;
|
||||
meth->name = eina_stringshare_ref(def->name);
|
||||
FILL_BASE(meth->base, ls, ls->line_number, ls->column);
|
||||
|
||||
def->function_pointer = meth;
|
||||
|
||||
for (;;) switch (ls->t.kw)
|
||||
{
|
||||
case KW_at_protected:
|
||||
eo_lexer_syntax_error(ls, "protected invalid for function pointer");
|
||||
return NULL;
|
||||
case KW_at_const:
|
||||
CASE_LOCK(ls, const, "const qualifier");
|
||||
meth->obj_is_const = EINA_TRUE;
|
||||
break;
|
||||
case KW_at_class:
|
||||
eo_lexer_syntax_error(ls, "class invalid for function pointer");
|
||||
return NULL;
|
||||
case KW_at_c_only:
|
||||
CASE_LOCK(ls, c_only, "c_only qualifier");
|
||||
meth->is_c_only = EINA_TRUE;
|
||||
eo_lexer_get(ls);
|
||||
break;
|
||||
case KW_at_beta:
|
||||
CASE_LOCK(ls, beta, "beta qualifier");
|
||||
meth->is_beta = EINA_TRUE;
|
||||
eo_lexer_get(ls);
|
||||
break;
|
||||
default:
|
||||
goto body;
|
||||
}
|
||||
body:
|
||||
line = ls->line_number;
|
||||
col = ls->column;
|
||||
check_next(ls, '{');
|
||||
for (;;) switch (ls->t.kw)
|
||||
{
|
||||
case KW_return:
|
||||
CASE_LOCK(ls, return, "return");
|
||||
Eo_Ret_Def ret;
|
||||
parse_return(ls, &ret, EINA_FALSE);
|
||||
pop_type(ls);
|
||||
if (ret.default_ret_val)
|
||||
{
|
||||
eo_lexer_syntax_error(ls, "default return value invalid for function pointer");
|
||||
return NULL;
|
||||
}
|
||||
meth->get_ret_type = ret.type;
|
||||
meth->get_return_doc = ret.doc;
|
||||
meth->get_ret_val = NULL;
|
||||
meth->get_return_warn_unused = EINA_FALSE;
|
||||
break;
|
||||
case KW_legacy: // FIXME Do legacy and eo make sense for these new function pointer stuff?
|
||||
eo_lexer_syntax_error(ls, "legacy invalid for function pointer");
|
||||
return NULL;
|
||||
case KW_eo:
|
||||
eo_lexer_syntax_error(ls, "eo name invalid for function pointer");
|
||||
return NULL;
|
||||
case KW_params:
|
||||
CASE_LOCK(ls, params, "params definition");
|
||||
parse_params(ls, &meth->params, EINA_TRUE, EINA_FALSE);
|
||||
break;
|
||||
default:
|
||||
goto end;
|
||||
}
|
||||
end:
|
||||
check_match(ls, '}', '{', line, col);
|
||||
check_next(ls, ';');
|
||||
FILL_DOC(ls, def, doc);
|
||||
return def;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_method(Eo_Lexer *ls)
|
||||
{
|
||||
|
@ -2154,6 +2256,12 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot)
|
|||
pop_typedecl(ls);
|
||||
break;
|
||||
}
|
||||
case KW_function:
|
||||
{
|
||||
database_type_add(parse_function_pointer(ls));
|
||||
pop_typedecl(ls);
|
||||
break;
|
||||
}
|
||||
case KW_const:
|
||||
case KW_var:
|
||||
{
|
||||
|
|
|
@ -179,6 +179,7 @@ struct _Eolian_Typedecl
|
|||
Eina_List *namespaces;
|
||||
Eina_Hash *fields;
|
||||
Eina_List *field_list;
|
||||
Eolian_Function *function_pointer;
|
||||
Eolian_Documentation *doc;
|
||||
Eina_Stringshare *legacy;
|
||||
Eina_Stringshare *freefunc;
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import function_types;
|
||||
|
||||
class Function_As_Argument {
|
||||
methods {
|
||||
set_cb {
|
||||
params {
|
||||
cb: SimpleFunc;
|
||||
}
|
||||
}
|
||||
|
||||
set_nonull_cb {
|
||||
params {
|
||||
cb: VoidFunc @nonull;
|
||||
}
|
||||
}
|
||||
|
||||
call_cb {
|
||||
params {
|
||||
a: int;
|
||||
b: double;
|
||||
}
|
||||
return: own(string);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#define EFL_BETA_API_SUPPORT
|
||||
#include <Eo.h>
|
||||
#include "function_as_argument.eo.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
} Function_As_Argument_Data;
|
||||
|
||||
EOLIAN static void
|
||||
_function_as_argument_set_cb(Eo *obj, Function_As_Argument_Data *pd, void *cb_data, SimpleFunc cb, Eina_Free_Cb cb_free_cb)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_function_as_argument_set_nonull_cb(Eo *obj, Function_As_Argument_Data *pd, void *cb_data, VoidFunc cb, Eina_Free_Cb cb_free_cb)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
EOLIAN static const char *
|
||||
_function_as_argument_call_cb(Eo *obj, Function_As_Argument_Data *pd, int a, double b)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#include "function_as_argument.eo.c"
|
|
@ -0,0 +1,49 @@
|
|||
|
||||
void _function_as_argument_set_cb(Eo *obj, Function_As_Argument_Data *pd, void *cb_data, SimpleFunc cb, Eina_Free_Cb cb_free_cb);
|
||||
|
||||
EOAPI EFL_VOID_FUNC_BODYV(function_as_argument_set_cb, EFL_FUNC_CALL(cb_data, cb, cb_free_cb), void *cb_data, SimpleFunc cb, Eina_Free_Cb cb_free_cb);
|
||||
|
||||
void _function_as_argument_set_nonull_cb(Eo *obj, Function_As_Argument_Data *pd, void *cb_data, VoidFunc cb, Eina_Free_Cb cb_free_cb);
|
||||
|
||||
EOAPI EFL_VOID_FUNC_BODYV(function_as_argument_set_nonull_cb, EFL_FUNC_CALL(cb_data, cb, cb_free_cb), void *cb_data, VoidFunc cb, Eina_Free_Cb cb_free_cb);
|
||||
|
||||
const char *_function_as_argument_call_cb(Eo *obj, Function_As_Argument_Data *pd, int a, double b);
|
||||
|
||||
EOAPI EFL_FUNC_BODYV(function_as_argument_call_cb, const char *, NULL, EFL_FUNC_CALL(a, b), int a, double b);
|
||||
|
||||
static Eina_Bool
|
||||
_function_as_argument_class_initializer(Efl_Class *klass)
|
||||
{
|
||||
const Efl_Object_Ops *opsp = NULL, *copsp = NULL;
|
||||
|
||||
#ifndef FUNCTION_AS_ARGUMENT_EXTRA_OPS
|
||||
#define FUNCTION_AS_ARGUMENT_EXTRA_OPS
|
||||
#endif
|
||||
|
||||
EFL_OPS_DEFINE(ops,
|
||||
EFL_OBJECT_OP_FUNC(function_as_argument_set_cb, _function_as_argument_set_cb),
|
||||
EFL_OBJECT_OP_FUNC(function_as_argument_set_nonull_cb, _function_as_argument_set_nonull_cb),
|
||||
EFL_OBJECT_OP_FUNC(function_as_argument_call_cb, _function_as_argument_call_cb),
|
||||
FUNCTION_AS_ARGUMENT_EXTRA_OPS
|
||||
);
|
||||
opsp = &ops;
|
||||
|
||||
#ifdef FUNCTION_AS_ARGUMENT_EXTRA_CLASS_OPS
|
||||
EFL_OPS_DEFINE(cops, FUNCTION_AS_ARGUMENT_EXTRA_CLASS_OPS);
|
||||
copsp = &cops;
|
||||
#endif
|
||||
|
||||
return efl_class_functions_set(klass, opsp, copsp);
|
||||
}
|
||||
|
||||
static const Efl_Class_Description _function_as_argument_class_desc = {
|
||||
EO_VERSION,
|
||||
"Function_As_Argument",
|
||||
EFL_CLASS_TYPE_REGULAR,
|
||||
sizeof(Function_As_Argument_Data),
|
||||
_function_as_argument_class_initializer,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
EFL_DEFINE_CLASS(function_as_argument_class_get, &_function_as_argument_class_desc, NULL, NULL);
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef _EOLIAN_FUNCTION_POINTERS_H_
|
||||
#define _EOLIAN_FUNCTION_POINTERS_H_
|
||||
|
||||
#ifndef _FUNCTION_AS_ARGUMENT_EO_CLASS_TYPE
|
||||
#define _FUNCTION_AS_ARGUMENT_EO_CLASS_TYPE
|
||||
|
||||
typedef Eo Function_As_Argument;
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _FUNCTION_AS_ARGUMENT_EO_TYPES
|
||||
#define _FUNCTION_AS_ARGUMENT_EO_TYPES
|
||||
|
||||
|
||||
#endif
|
||||
#define FUNCTION_AS_ARGUMENT_CLASS function_as_argument_class_get()
|
||||
|
||||
EWAPI const Efl_Class *function_as_argument_class_get(void);
|
||||
|
||||
EOAPI void function_as_argument_set_cb(Eo *obj, void *cb_data, SimpleFunc cb, Eina_Free_Cb cb_free_cb);
|
||||
|
||||
EOAPI void function_as_argument_set_nonull_cb(Eo *obj, void *cb_data, VoidFunc cb, Eina_Free_Cb cb_free_cb) EINA_ARG_NONNULL(3);
|
||||
|
||||
EOAPI const char *function_as_argument_call_cb(Eo *obj, int a, double b);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
|
||||
// typedef void (*VoidFunc)(void *data);
|
||||
function VoidFunc {
|
||||
};
|
||||
|
||||
// typedef const char *(*SimpleFunc)(void *data, int a, double b);
|
||||
function SimpleFunc {
|
||||
params {
|
||||
a: int;
|
||||
b: double;
|
||||
}
|
||||
return: string;
|
||||
};
|
||||
|
||||
// typedef double (*ComplexFunc)(void *data, const char *a, const char **b);
|
||||
function ComplexFunc {
|
||||
params {
|
||||
@in c: string;
|
||||
@out d: own(string);
|
||||
}
|
||||
return: double;
|
||||
};
|
||||
|
||||
// typedef void (*FuncAsArgFunc)(void *data, VoidFunc cb, SimpleFunc another_cb);
|
||||
function FuncAsArgFunc {
|
||||
params {
|
||||
cb: VoidFunc;
|
||||
another_cb: SimpleFunc;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef _EOLIAN_FUNCTION_POINTERS_H_
|
||||
#define _EOLIAN_FUNCTION_POINTERS_H_
|
||||
|
||||
#ifndef _FUNCTION_TYPES_EOT_TYPES
|
||||
#define _FUNCTION_TYPES_EOT_TYPES
|
||||
|
||||
typedef void (*VoidFunc)(void *data);
|
||||
|
||||
typedef const char * (*SimpleFunc)(void *data, int a, double b);
|
||||
|
||||
typedef double (*ComplexFunc)(void *data, const char * c, const char * d);
|
||||
|
||||
typedef void (*FuncAsArgFunc)(void *data, void *cb_data, VoidFunc cb, Eina_Free_Cb cb_free_cb, void *another_cb_data, SimpleFunc another_cb, Eina_Free_Cb another_cb_free_cb);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -186,6 +186,37 @@ START_TEST(eolian_docs)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(eolian_function_pointers)
|
||||
{
|
||||
|
||||
// .eot
|
||||
char output_filepath[PATH_MAX] = "";
|
||||
snprintf(output_filepath, PATH_MAX, "%s/eolian_function_pointers",
|
||||
eina_environment_tmp_get());
|
||||
_remove_ref(output_filepath, "h");
|
||||
fail_if(0 != _eolian_gen_execute(PACKAGE_DATA_DIR"/data/function_types.eot", "-gh", output_filepath));
|
||||
fail_if(!_files_compare(PACKAGE_DATA_DIR"/data/function_types_ref.h", output_filepath, "h"));
|
||||
|
||||
// .eo.h
|
||||
_remove_ref(output_filepath, "h");
|
||||
fail_if(0 != _eolian_gen_execute(PACKAGE_DATA_DIR"/data/function_as_argument.eo", "-gh", output_filepath));
|
||||
fail_if(!_files_compare(PACKAGE_DATA_DIR"/data/function_as_argument_ref.h", output_filepath, "h"));
|
||||
|
||||
// .eo.c
|
||||
_remove_ref(output_filepath, "c");
|
||||
fail_if(0 != _eolian_gen_execute(PACKAGE_DATA_DIR"/data/function_as_argument.eo", "-gc", output_filepath));
|
||||
fail_if(!_files_compare(PACKAGE_DATA_DIR"/data/function_as_argument_ref.c", output_filepath, "c"));
|
||||
|
||||
// .eo.imp.c
|
||||
_remove_ref(output_filepath, "c");
|
||||
fail_if(0 != _eolian_gen_execute(PACKAGE_DATA_DIR"/data/function_as_argument.eo", "-gi", output_filepath));
|
||||
fail_if(!_files_compare(PACKAGE_DATA_DIR"/data/function_as_argument_impl_ref.c", output_filepath, "c"));
|
||||
/* Check that nothing is added */
|
||||
fail_if(0 != _eolian_gen_execute(PACKAGE_DATA_DIR"/data/function_as_argument.eo", "-gi", output_filepath));
|
||||
fail_if(!_files_compare(PACKAGE_DATA_DIR"/data/function_as_argument_impl_ref.c", output_filepath, "c"));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void eolian_generation_test(TCase *tc)
|
||||
{
|
||||
tcase_add_test(tc, eolian_types_generation);
|
||||
|
@ -195,4 +226,5 @@ void eolian_generation_test(TCase *tc)
|
|||
tcase_add_test(tc, eolian_functions_descriptions);
|
||||
tcase_add_test(tc, eolian_import);
|
||||
tcase_add_test(tc, eolian_docs);
|
||||
tcase_add_test(tc, eolian_function_pointers);
|
||||
}
|
||||
|
|
|
@ -1387,6 +1387,172 @@ START_TEST(eolian_docs)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(eolian_function_types)
|
||||
{
|
||||
const Eolian_Typedecl *decl = NULL;
|
||||
const Eolian_Typedecl *arg_decl = NULL;
|
||||
const Eolian_Type *type = NULL;
|
||||
const Eolian_Function *fid = NULL;
|
||||
const Eolian_Function_Parameter *param = NULL;
|
||||
const Eolian_Unit *unit = NULL;
|
||||
Eina_Iterator *iter = NULL;
|
||||
const char* type_name = NULL;
|
||||
void *dummy;
|
||||
|
||||
eolian_init();
|
||||
|
||||
fail_if(!eolian_directory_scan(PACKAGE_DATA_DIR"/data"));
|
||||
|
||||
/* Parsing */
|
||||
fail_if(!(unit = eolian_file_parse(PACKAGE_DATA_DIR"/data/function_types.eot")));
|
||||
|
||||
/* void func(void); */
|
||||
fail_if(!(decl = eolian_typedecl_alias_get_by_name(unit, "VoidFunc")));
|
||||
fail_if(eolian_typedecl_type_get(decl) != EOLIAN_TYPEDECL_FUNCTION_POINTER);
|
||||
|
||||
fail_if(!(fid = eolian_typedecl_function_pointer_get(decl)));
|
||||
fail_if(eolian_function_type_get(fid) != EOLIAN_FUNCTION_POINTER);
|
||||
|
||||
fail_if((eolian_function_return_type_get(fid, EOLIAN_FUNCTION_POINTER))); // void is null_return_type?
|
||||
fail_if((eolian_function_parameters_get(fid)));
|
||||
|
||||
/* Function pointer with return and parameters */
|
||||
fail_if(!(decl = eolian_typedecl_alias_get_by_name(unit, "SimpleFunc")));
|
||||
fail_if(eolian_typedecl_type_get(decl) != EOLIAN_TYPEDECL_FUNCTION_POINTER);
|
||||
|
||||
fail_if(!(fid = eolian_typedecl_function_pointer_get(decl)));
|
||||
fail_if(eolian_function_type_get(fid) != EOLIAN_FUNCTION_POINTER);
|
||||
fail_if(strcmp(eolian_function_name_get(fid), "SimpleFunc"));
|
||||
|
||||
fail_if(!(type = eolian_function_return_type_get(fid, EOLIAN_FUNCTION_POINTER))); // void is null_return_type?
|
||||
fail_if(!(type_name = eolian_type_c_type_get(type)));
|
||||
fail_if(strcmp(type_name, "const char *"));
|
||||
fail_if(!(iter = (eolian_function_parameters_get(fid))));
|
||||
|
||||
fail_if(!(eina_iterator_next(iter, (void**)¶m)));
|
||||
fail_if(strcmp(eolian_parameter_name_get(param), "a"));
|
||||
fail_if(!(type = eolian_parameter_type_get(param)));
|
||||
fail_if(!(type_name = eolian_type_c_type_get(type)));
|
||||
fail_if(strcmp(type_name, "int"));
|
||||
|
||||
fail_if(!(eina_iterator_next(iter, (void**)¶m)));
|
||||
fail_if(strcmp(eolian_parameter_name_get(param), "b"));
|
||||
fail_if(!(type = eolian_parameter_type_get(param)));
|
||||
fail_if(!(type_name = eolian_type_c_type_get(type)));
|
||||
fail_if(strcmp(type_name, "double"));
|
||||
|
||||
fail_if(eina_iterator_next(iter, &dummy));
|
||||
|
||||
/* Function pointer with parameter attributes (in/out) */
|
||||
fail_if(!(decl = eolian_typedecl_alias_get_by_name(unit, "ComplexFunc")));
|
||||
fail_if(eolian_typedecl_type_get(decl) != EOLIAN_TYPEDECL_FUNCTION_POINTER);
|
||||
|
||||
fail_if(!(fid = eolian_typedecl_function_pointer_get(decl)));
|
||||
fail_if(eolian_function_type_get(fid) != EOLIAN_FUNCTION_POINTER);
|
||||
|
||||
fail_if(!(type = eolian_function_return_type_get(fid, EOLIAN_FUNCTION_POINTER)));
|
||||
fail_if(!(type_name = eolian_type_c_type_get(type)));
|
||||
fail_if(strcmp(type_name, "double"));
|
||||
fail_if(!(iter = (eolian_function_parameters_get(fid))));
|
||||
|
||||
/* in string */
|
||||
fail_if(!(eina_iterator_next(iter, (void**)¶m)));
|
||||
fail_if(strcmp(eolian_parameter_name_get(param), "c"));
|
||||
fail_if(!(type = eolian_parameter_type_get(param)));
|
||||
fail_if(eolian_parameter_direction_get(param) != EOLIAN_IN_PARAM);
|
||||
fail_if(eolian_type_is_own(type));
|
||||
fail_if(!(type_name = eolian_type_c_type_get(type)));
|
||||
fail_if(strcmp(type_name, "const char *"));
|
||||
|
||||
/*out own string */
|
||||
fail_if(!(eina_iterator_next(iter, (void**)¶m)));
|
||||
fail_if(strcmp(eolian_parameter_name_get(param), "d"));
|
||||
fail_if(eolian_parameter_direction_get(param) != EOLIAN_OUT_PARAM);
|
||||
fail_if(!(type = eolian_parameter_type_get(param)));
|
||||
fail_if(!eolian_type_is_own(type));
|
||||
fail_if(!(type_name = eolian_type_c_type_get(type)));
|
||||
fail_if(strcmp(type_name, "const char *"));
|
||||
|
||||
fail_if(eina_iterator_next(iter, &dummy));
|
||||
|
||||
/* Function pointer receiving another function pointer */
|
||||
fail_if(!(decl = eolian_typedecl_alias_get_by_name(unit, "FuncAsArgFunc")));
|
||||
fail_if(eolian_typedecl_type_get(decl) != EOLIAN_TYPEDECL_FUNCTION_POINTER);
|
||||
|
||||
fail_if(!(fid = eolian_typedecl_function_pointer_get(decl)));
|
||||
fail_if(eolian_function_type_get(fid) != EOLIAN_FUNCTION_POINTER);
|
||||
|
||||
fail_if(eolian_function_return_type_get(fid, EOLIAN_FUNCTION_POINTER));
|
||||
|
||||
fail_if(!(iter = (eolian_function_parameters_get(fid))));
|
||||
|
||||
fail_if(!(eina_iterator_next(iter, (void**)¶m)));
|
||||
fail_if(strcmp(eolian_parameter_name_get(param), "cb"));
|
||||
fail_if(!(type = eolian_parameter_type_get(param)));
|
||||
fail_if(eolian_parameter_direction_get(param) != EOLIAN_IN_PARAM);
|
||||
fail_if(eolian_type_is_own(type));
|
||||
fail_if(!(type_name = eolian_type_name_get(type)));
|
||||
fail_if(strcmp(type_name, "VoidFunc"));
|
||||
fail_if(!(arg_decl = eolian_type_typedecl_get(type)));
|
||||
fail_if(eolian_typedecl_type_get(arg_decl) != EOLIAN_TYPEDECL_FUNCTION_POINTER);
|
||||
|
||||
fail_if(!(eina_iterator_next(iter, (void**)¶m)));
|
||||
fail_if(strcmp(eolian_parameter_name_get(param), "another_cb"));
|
||||
fail_if(eolian_parameter_direction_get(param) != EOLIAN_IN_PARAM);
|
||||
fail_if(!(type = eolian_parameter_type_get(param)));
|
||||
fail_if(eolian_type_is_own(type));
|
||||
fail_if(eolian_type_type_get(type) != EOLIAN_TYPE_REGULAR);
|
||||
fail_if(!(type_name = eolian_type_name_get(type)));
|
||||
fail_if(strcmp(type_name, "SimpleFunc"));
|
||||
fail_if(!(arg_decl = eolian_type_typedecl_get(type)));
|
||||
fail_if(eolian_typedecl_type_get(arg_decl) != EOLIAN_TYPEDECL_FUNCTION_POINTER);
|
||||
|
||||
fail_if(eina_iterator_next(iter, &dummy));
|
||||
|
||||
eolian_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(eolian_function_as_arguments)
|
||||
{
|
||||
const Eolian_Class *cls = NULL;
|
||||
const Eolian_Function *fid = NULL;
|
||||
const Eolian_Type *type = NULL;
|
||||
const Eolian_Typedecl *arg_decl = NULL;
|
||||
const Eolian_Function_Parameter *param = NULL;
|
||||
const Eolian_Unit *unit = NULL;
|
||||
Eina_Iterator *iter = NULL;
|
||||
const char *type_name = NULL;
|
||||
void *dummy;
|
||||
|
||||
eolian_init();
|
||||
|
||||
fail_if(!eolian_directory_scan(PACKAGE_DATA_DIR"/data"));
|
||||
|
||||
fail_if(!(unit = eolian_file_parse(PACKAGE_DATA_DIR"/data/function_as_argument.eo")));
|
||||
|
||||
fail_if(!(cls = eolian_class_get_by_name(unit, "Function_As_Argument")));
|
||||
|
||||
fail_if(!(fid = eolian_class_function_get_by_name(cls, "set_cb", EOLIAN_METHOD)));
|
||||
|
||||
fail_if(!(iter = (eolian_function_parameters_get(fid))));
|
||||
|
||||
fail_if(!(eina_iterator_next(iter, (void**)¶m)));
|
||||
fail_if(strcmp(eolian_parameter_name_get(param), "cb"));
|
||||
fail_if(!(type = eolian_parameter_type_get(param)));
|
||||
fail_if(eolian_parameter_direction_get(param) != EOLIAN_IN_PARAM);
|
||||
fail_if(eolian_type_is_own(type));
|
||||
fail_if(!(type_name = eolian_type_name_get(type)));
|
||||
fail_if(strcmp(type_name, "SimpleFunc"));
|
||||
fail_if(!(arg_decl = eolian_type_typedecl_get(type)));
|
||||
fail_if(eolian_typedecl_type_get(arg_decl) != EOLIAN_TYPEDECL_FUNCTION_POINTER);
|
||||
|
||||
fail_if(eina_iterator_next(iter, &dummy));
|
||||
|
||||
eolian_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void eolian_parsing_test(TCase *tc)
|
||||
{
|
||||
tcase_add_test(tc, eolian_simple_parsing);
|
||||
|
@ -1408,4 +1574,6 @@ void eolian_parsing_test(TCase *tc)
|
|||
tcase_add_test(tc, eolian_import);
|
||||
tcase_add_test(tc, eolian_decl);
|
||||
tcase_add_test(tc, eolian_docs);
|
||||
tcase_add_test(tc, eolian_function_types);
|
||||
tcase_add_test(tc, eolian_function_as_arguments);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue