eolian_cxx: Add implicit conversion of the returned pointer of C++ wrappers

Overloaded address-of operator for C++ Eolian wrappers for implicit converting
to any ancestor pointer type when getting the object memory address.

Added new grammars to aid the creation of the pointer wrappers
responsible of doing the implicit conversions.

Added a unit test which checks the address-of overload for arbitrary classes.
Added new .eo files to be used in it.
This commit is contained in:
Vitor Sousa 2014-12-23 17:40:11 -02:00
parent 6519ae6ed9
commit 0685885c2a
13 changed files with 305 additions and 2 deletions

View File

@ -55,6 +55,9 @@ bin_eolian_cxx_eolian_cxx_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@
if EFL_ENABLE_TESTS
EOLIAN_FLAGS += \
-I$(srcdir)
check_PROGRAMS += tests/eolian_cxx/eolian_cxx_suite
TESTS += tests/eolian_cxx/eolian_cxx_suite
@ -62,15 +65,29 @@ tests_eolian_cxx_eolian_cxx_suite_SOURCES = \
tests/eolian_cxx/eolian_cxx_suite.cc \
tests/eolian_cxx/eolian_cxx_test_parse.cc \
tests/eolian_cxx/callback.c \
tests/eolian_cxx/a.c \
tests/eolian_cxx/b.c \
tests/eolian_cxx/c.c \
tests/eolian_cxx/d.c \
tests/eolian_cxx/eolian_cxx_test_callback.cc \
tests/eolian_cxx/eolian_cxx_test_address_of.cc \
tests/eolian_cxx/eolian_cxx_test_wrapper.cc \
tests/eolian_cxx/eolian_cxx_test_generate.cc
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_callback.$(OBJEXT): tests/eolian_cxx/callback.eo.hh
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_address_of.$(OBJEXT): tests/eolian_cxx/a.eo.hh tests/eolian_cxx/b.eo.hh tests/eolian_cxx/c.eo.hh tests/eolian_cxx/d.eo.hh
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-callback.$(OBJEXT): tests/eolian_cxx/callback.eo.c tests/eolian_cxx/callback.eo.h
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-a.$(OBJEXT): tests/eolian_cxx/a.eo.c tests/eolian_cxx/a.eo.h
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-b.$(OBJEXT): tests/eolian_cxx/b.eo.c tests/eolian_cxx/b.eo.h
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-c.$(OBJEXT): tests/eolian_cxx/c.eo.c tests/eolian_cxx/c.eo.h
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-d.$(OBJEXT): tests/eolian_cxx/d.eo.c tests/eolian_cxx/d.eo.h
CLEANFILES += tests/eolian_cxx/callback.eo.hh tests/eolian_cxx/callback.eo.c tests/eolian_cxx/callback.eo.h
CLEANFILES += tests/eolian_cxx/callback.eo.hh tests/eolian_cxx/callback.eo.c tests/eolian_cxx/callback.eo.h \
tests/eolian_cxx/a.eo.hh tests/eolian_cxx/a.eo.c tests/eolian_cxx/a.eo.h \
tests/eolian_cxx/b.eo.hh tests/eolian_cxx/b.eo.c tests/eolian_cxx/b.eo.h \
tests/eolian_cxx/c.eo.hh tests/eolian_cxx/c.eo.c tests/eolian_cxx/c.eo.h \
tests/eolian_cxx/d.eo.hh tests/eolian_cxx/d.eo.c tests/eolian_cxx/d.eo.h
tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS = \
-I$(top_builddir)/src/lib/efl \
@ -93,7 +110,12 @@ tests_eolian_cxx_eolian_cxx_suite_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@
endif
EXTRA_DIST += tests/eolian_cxx/callback.eo
EXTRA_DIST += tests/eolian_cxx/callback.eo \
tests/eolian_cxx/a.eo \
tests/eolian_cxx/b.eo \
tests/eolian_cxx/c.eo \
tests/eolian_cxx/d.eo
include Makefile_Eolian_Cxx_Helper.am
endif

View File

@ -201,6 +201,18 @@ struct extension_inheritance<concrete>
};
};
struct concrete_address_of
{
explicit concrete_address_of(void* p) : p(p) {}
void* p;
};
struct concrete_address_const_of
{
explicit concrete_address_const_of(void const* p) : p(p) {}
void const* p;
};
}
/// @brief Downcast @p U to @p T.

View File

@ -95,6 +95,104 @@ operator<<(std::ostream& out, class_implicit_conversion_definition const& x)
return out;
}
struct address_of_to_pointer
{
eo_class const& _cls;
bool _is_const;
address_of_to_pointer(eo_class const& cls, bool is_const)
: _cls(cls), _is_const(is_const)
{}
};
inline std::ostream&
operator<<(std::ostream& out, address_of_to_pointer const& x)
{
out << "operator " << full_name(x._cls) << (x._is_const ? " const" : "")
<< "*() const { return static_cast<" << full_name(x._cls)
<< (x._is_const ? " const" : "")
<< "*>(static_cast<D const*>(this)->p); }";
return out;
}
struct abstract_address_of
{
eo_class const& _cls;
abstract_address_of(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, abstract_address_of const& x)
{
out << tab(1) << "template <typename D>" << endl
<< tab(1) << "struct address_of" << endl
<< tab(1) << "{" << endl
<< tab(2) << address_of_to_pointer(x._cls, false) << endl
<< tab(2) << address_of_to_pointer(x._cls, true) << endl
<< tab(1) << "};" << endl << endl;
out << tab(1) << "template <typename D>" << endl
<< tab(1) << "struct address_const_of" << endl
<< tab(1) << "{" << endl
<< tab(2) << address_of_to_pointer(x._cls, true) << endl
<< tab(1) << "};" << endl << endl;
return out;
}
struct address_of_inheritance
{
eo_class const& _cls;
std::string _struct_name;
address_of_inheritance(eo_class const& cls, std::string const& struct_name)
: _cls(cls), _struct_name(struct_name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, address_of_inheritance const& x)
{
for (std::string const& parent : x._cls.parents)
{
out << tab(2) << ", ::" << abstract_namespace << "::" << parent << "::"
<< x._struct_name << "<" << x._struct_name << ">" << endl;
}
return out;
}
struct concrete_address_of
{
eo_class const& _cls;
concrete_address_of(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, concrete_address_of const& x)
{
std::vector<std::string> names {"address_of", "address_const_of"};
for (int is_const = 0; is_const != 2; ++is_const)
{
std::string const& name = names[is_const];
out << tab(1) << "struct " << name << endl
<< tab(2) << ": " << abstract_full_name(x._cls) << "::"
<< name << "<" << name << ">" << endl
<< address_of_inheritance(x._cls, name)
<< tab(2) << ", ::efl::eo::detail::concrete_" << name << endl
<< tab(1) << "{" << endl
<< tab(2) << "explicit " << name << "(" << full_name(x._cls)
<< (is_const ? " const" : "")
<< "* p)" << endl
<< tab(3) << ": ::efl::eo::detail::concrete_" << name << "(p)" << endl
<< tab(2) << "{}" << endl
<< tab(1) << "};" << endl
<< tab(1) << name << " operator&()"
<< (is_const ? " const" : "")
<< " { return " << name << "(this); }" << endl << endl;
}
return out;
}
inline void
eo_class_generator(std::ostream& out, eo_class const& cls)
{
@ -110,6 +208,7 @@ eo_class_generator(std::ostream& out, eo_class const& cls)
<< events(cls)
<< eo_class_getter(cls)
<< class_implicit_conversion_declaration(cls)
<< abstract_address_of(cls)
<< "private:" << endl
<< concrete_eo_ptr_getter(cls)
<< "};" << endl << endl
@ -129,6 +228,7 @@ eo_class_generator(std::ostream& out, eo_class const& cls)
<< function_declarations(cls)
<< events(cls)
<< eo_class_getter(cls)
<< concrete_address_of(cls)
<< "private:" << endl
<< function_call_constructor_methods(cls)
<< tab(2) << "Eo* _concrete_eo_ptr() const { return _eo_ptr(); }" << endl

24
src/tests/eolian_cxx/a.c Normal file
View File

@ -0,0 +1,24 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eo.h>
#include "a.eo.h"
struct _A_Data
{
int callbacks;
};
typedef struct _A_Data A_Data;
#define MY_CLASS A_CLASS
static void _a_eo_base_constructor(Eo *obj EINA_UNUSED, A_Data *pd EINA_UNUSED)
{
eo_do_super(obj, MY_CLASS, eo_constructor());
}
#include "a.eo.c"

View File

@ -0,0 +1,8 @@
class A (Eo.Base)
{
legacy_prefix: null;
data: A_Data;
implements {
Eo.Base.constructor;
}
}

25
src/tests/eolian_cxx/b.c Normal file
View File

@ -0,0 +1,25 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eo.h>
#include "a.eo.h"
#include "b.eo.h"
struct _B_Data
{
int callbacks;
};
typedef struct _B_Data B_Data;
#define MY_CLASS B_CLASS
static void _b_eo_base_constructor(Eo *obj EINA_UNUSED, B_Data *pd EINA_UNUSED)
{
eo_do_super(obj, MY_CLASS, eo_constructor());
}
#include "b.eo.c"

View File

@ -0,0 +1,8 @@
class B (A)
{
legacy_prefix: null;
data: B_Data;
implements {
Eo.Base.constructor;
}
}

25
src/tests/eolian_cxx/c.c Normal file
View File

@ -0,0 +1,25 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eo.h>
#include "a.eo.h"
#include "c.eo.h"
struct _C_Data
{
int callbacks;
};
typedef struct _C_Data C_Data;
#define MY_CLASS C_CLASS
static void _c_eo_base_constructor(Eo *obj EINA_UNUSED, C_Data *pd EINA_UNUSED)
{
eo_do_super(obj, MY_CLASS, eo_constructor());
}
#include "c.eo.c"

View File

@ -0,0 +1,8 @@
class C (A)
{
legacy_prefix: null;
data: C_Data;
implements {
Eo.Base.constructor;
}
}

27
src/tests/eolian_cxx/d.c Normal file
View File

@ -0,0 +1,27 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eo.h>
#include "a.eo.h"
#include "b.eo.h"
#include "c.eo.h"
#include "d.eo.h"
struct _D_Data
{
int callbacks;
};
typedef struct _D_Data D_Data;
#define MY_CLASS D_CLASS
static void _d_eo_base_constructor(Eo *obj EINA_UNUSED, D_Data *pd EINA_UNUSED)
{
eo_do_super(obj, MY_CLASS, eo_constructor());
}
#include "d.eo.c"

View File

@ -0,0 +1,8 @@
class D (B, C)
{
legacy_prefix: null;
data: D_Data;
implements {
Eo.Base.constructor;
}
}

View File

@ -7,6 +7,7 @@ void eolian_cxx_test_parse(TCase* tc);
void eolian_cxx_test_wrapper(TCase* tc);
void eolian_cxx_test_generate(TCase* tc);
void eolian_cxx_test_callback(TCase* tc);
void eolian_cxx_test_address_of(TCase* tc);
typedef struct _Eolian_Cxx_Test_Case Eolian_Cxx_Test_Case;
struct _Eolian_Cxx_Test_Case
@ -20,6 +21,7 @@ static const Eolian_Cxx_Test_Case etc[] = {
{ "Eolian-Cxx Wrapper", eolian_cxx_test_wrapper },
{ "Eolian-Cxx Generation", eolian_cxx_test_generate },
{ "Eolian-Cxx Callback", eolian_cxx_test_callback },
{ "Eolian-Cxx Address_of", eolian_cxx_test_address_of },
{ NULL, NULL }
};

View File

@ -0,0 +1,34 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <a.eo.hh>
#include <b.eo.hh>
#include <c.eo.hh>
#include <d.eo.hh>
#include <check.h>
START_TEST(eolian_cxx_test_addess_of_conversions)
{
efl::eo::eo_init init;
d d_obj;
a* a_ptr = &d_obj;
b* b_ptr = &d_obj;
c* c_ptr = &d_obj;
d* d_ptr = &d_obj;
fail_unless(a_ptr == (void*) b_ptr);
fail_unless(a_ptr == (void*) c_ptr);
fail_unless(a_ptr == (void*) d_ptr);
}
END_TEST
void
eolian_cxx_test_address_of(TCase* tc)
{
tcase_add_test(tc, eolian_cxx_test_addess_of_conversions);
}