efl_mono: Proper support for @class methods.
Previously, class methods were implemented as regular instance methods. This commits generates C# static methods for @class methods on the *Concrete classes (and their childs).
This commit is contained in:
parent
a252c3445d
commit
65f868786a
|
@ -48,6 +48,7 @@ lib_efl_mono_libefl_mono_dll_sources = \
|
|||
|
||||
efl_mono_test_files = \
|
||||
tests/efl_mono/test_testing.eo \
|
||||
tests/efl_mono/test_child.eo \
|
||||
tests/efl_mono/test_numberwrapper.eo \
|
||||
tests/efl_mono/mono_test_driver.sh
|
||||
|
||||
|
@ -382,10 +383,11 @@ tests_efl_mono_libefl_mono_native_test_la_LDFLAGS = -rpath $(abs_top_builddir)/t
|
|||
tests_efl_mono_libefl_mono_native_test_la_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@ @USE_ECORE_INTERNAL_LIBS@ @USE_ELDBUS_INTERNAL_LIBS@
|
||||
tests_efl_mono_libefl_mono_native_test_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
||||
tests/efl_mono/libefl_mono_native_test.c: tests/efl_mono/test_testing.eo.h tests/efl_mono/test_testing.eo.c tests/efl_mono/test_numberwrapper.eo.h tests/efl_mono/test_numberwrapper.eo.c
|
||||
tests/efl_mono/libefl_mono_native_test.c: tests/efl_mono/test_testing.eo.h tests/efl_mono/test_testing.eo.c tests/efl_mono/test_child.eo.h tests/efl_mono/test_child.eo.c tests/efl_mono/test_numberwrapper.eo.h tests/efl_mono/test_numberwrapper.eo.c
|
||||
|
||||
# Intermediate C Sharp test DLL
|
||||
efl_mono_test_eolian_mono_files = tests/efl_mono/test_testing.eo.cs \
|
||||
tests/efl_mono/test_child.eo.cs \
|
||||
tests/efl_mono/test_numberwrapper.eo.cs
|
||||
|
||||
tests/efl_mono/libefl_mono_test.dll: $(efl_mono_test_eolian_mono_files) tests/efl_mono/$(am__dirstamp) lib/efl_mono/libefl_mono.dll tests/efl_mono/libefl_mono_native_test.la tests/efl_mono/libefl_mono_test.dll.config
|
||||
|
@ -456,7 +458,7 @@ tests/efl_mono/%.eo.cs: tests/efl_mono/%.eo $(_EOLIAN_MONO_DEP)
|
|||
$(MKDIR_P) $(dir $@); \
|
||||
$(EOLIAN_MONO) $(EOLIAN_FLAGS) $(EOLIAN_MONO_FLAGS) --dllimport "@DLIB_PREFIX_MONO@efl_mono_native_test@DLIB_SUFFIX_MONO@" -o $@ $(ALL_EO_REFS) $<
|
||||
|
||||
CLEANFILES += tests/efl_mono/libefl_mono_test.dll tests/efl_mono/test_testing.eo.cs tests/efl_mono/test_numberwrapper.eo.cs tests/efl_mono/test_testing.eo.c tests/efl_mono/test_numberwrapper.eo.c tests/efl_mono/test_testing.eo.h tests/efl_mono/test_numberwrapper.eo.h tests/efl_mono/efl_mono.config
|
||||
CLEANFILES += tests/efl_mono/libefl_mono_test.dll tests/efl_mono/test_testing.eo.cs tests/efl_mono/test_child.eo.cs tests/efl_mono/test_numberwrapper.eo.cs tests/efl_mono/test_testing.eo.c tests/efl_mono/test_child.eo.c tests/efl_mono/test_numberwrapper.eo.c tests/efl_mono/test_testing.eo.h tests/efl_mono/test_child.eo.h tests/efl_mono/test_numberwrapper.eo.h tests/efl_mono/efl_mono.config
|
||||
|
||||
endif
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ struct function_declaration_generator
|
|||
template <typename OutputIterator, typename Context>
|
||||
bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
|
||||
{
|
||||
if(is_function_blacklisted(f.c_name))
|
||||
if(is_function_blacklisted(f.c_name) || f.is_static)
|
||||
return true;
|
||||
|
||||
if(!as_generator(documentation).generate(sink, f, context))
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "grammar/alternative.hpp"
|
||||
#include "grammar/attribute_reorder.hpp"
|
||||
#include "type.hh"
|
||||
#include "helpers.hh"
|
||||
#include "function_helpers.hh"
|
||||
#include "marshall_type.hh"
|
||||
#include "parameter.hh"
|
||||
|
@ -28,7 +29,7 @@ struct native_function_definition_generator
|
|||
template <typename OutputIterator, typename Context>
|
||||
bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
|
||||
{
|
||||
if(is_function_blacklisted(f.c_name))
|
||||
if(is_function_blacklisted(f.c_name) || f.is_static) // Only Concrete classes implement static methods.
|
||||
return true;
|
||||
else
|
||||
{
|
||||
|
@ -131,10 +132,11 @@ struct function_definition_generator
|
|||
template <typename OutputIterator, typename Context>
|
||||
bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
|
||||
{
|
||||
if(do_super && f.is_static) // Static methods goes only on Concrete classes.
|
||||
return true;
|
||||
if(is_function_blacklisted(f.c_name))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
|
||||
if(!as_generator
|
||||
("\n\n" << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(context).actual_library_name(f.filename) << ")]\n"
|
||||
<< scope_tab << eolian_mono::marshall_annotation(true)
|
||||
|
@ -159,11 +161,11 @@ struct function_definition_generator
|
|||
return false;
|
||||
|
||||
if(!as_generator
|
||||
(scope_tab << (do_super ? "virtual " : "") << "public " << return_type << " " << string << "(" << (parameter % ", ")
|
||||
(scope_tab << (do_super ? "virtual " : "") << "public " << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ")
|
||||
<< ") {\n "
|
||||
<< eolian_mono::function_definition_preamble() << string << "("
|
||||
<< (do_super ? "efl.eo.Globals.efl_super(" : "")
|
||||
<< "this.raw_handle"
|
||||
<< (f.is_static ? klass_get_name(f.klass) + "()": "this.raw_handle")
|
||||
<< (do_super ? ", this.raw_klass)" : "")
|
||||
<< *(", " << argument_invocation ) << ");\n"
|
||||
<< eolian_mono::function_definition_epilogue()
|
||||
|
@ -172,7 +174,6 @@ struct function_definition_generator
|
|||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool do_super;
|
||||
|
|
|
@ -28,7 +28,7 @@ struct function_registration_generator
|
|||
template <typename OutputIterator, typename Context>
|
||||
bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
|
||||
{
|
||||
if(is_function_blacklisted(f.c_name))
|
||||
if(is_function_blacklisted(f.c_name) || f.is_static) // Static methods aren't overrideable
|
||||
return true;
|
||||
else
|
||||
{
|
||||
|
|
|
@ -125,6 +125,21 @@ inline std::string klass_name_to_csharp(attributes::klass_name const& clsname)
|
|||
return output.str();
|
||||
}
|
||||
|
||||
inline std::string klass_get_name(attributes::klass_name const &clsname)
|
||||
{
|
||||
std::ostringstream output;
|
||||
|
||||
output << klass_name_to_csharp(clsname);
|
||||
output << "Concrete.";
|
||||
|
||||
for (auto namesp : clsname.namespaces)
|
||||
output << utils::to_lowercase(namesp) << "_";
|
||||
output << utils::to_lowercase(clsname.eolian_name);
|
||||
output << "_class_get";
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -69,12 +69,12 @@ static bool generate_equals_method(OutputIterator sink, Context const &context)
|
|||
|
||||
/* Get the actual number of functions of a class, checking for blacklisted ones */
|
||||
static std::size_t
|
||||
get_function_count(grammar::attributes::klass_def const& cls)
|
||||
get_inheritable_function_count(grammar::attributes::klass_def const& cls)
|
||||
{
|
||||
auto methods = cls.get_all_methods();
|
||||
return std::count_if(methods.cbegin(), methods.cend(), [](grammar::attributes::function_def const& func)
|
||||
{
|
||||
return !is_function_blacklisted(func.c_name);
|
||||
return !is_function_blacklisted(func.c_name) && !func.is_static;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -268,8 +268,9 @@ struct klass
|
|||
<< scope_tab << "}\n"
|
||||
<< scope_tab << "///<summary>Delegate for function to be called from inside the native constructor.</summary>\n"
|
||||
<< scope_tab << "public delegate void ConstructingMethod(" << string << " obj);\n"
|
||||
<< scope_tab << "///<summary>Returns the pointer the unerlying Eo class object. Used internally on class methods.</summary>\n"
|
||||
<< scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(concrete_cxt).actual_library_name(cls.filename)
|
||||
<< ")] private static extern System.IntPtr\n"
|
||||
<< ")] public static extern System.IntPtr\n"
|
||||
<< scope_tab << scope_tab << class_get_name << "();\n"
|
||||
<< (class_type == "class" ? "" : "/*")
|
||||
<< scope_tab << "///<summary>Creates a new instance.</summary>\n"
|
||||
|
@ -451,7 +452,7 @@ struct klass
|
|||
if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false;
|
||||
}
|
||||
|
||||
std::size_t function_count = get_function_count(cls);
|
||||
std::size_t function_count = get_inheritable_function_count(cls);
|
||||
|
||||
int function_registration_index = 0;
|
||||
auto index_generator = [&function_registration_index]
|
||||
|
|
|
@ -109,6 +109,9 @@ struct klass_name
|
|||
qualifier_def base_qualifier;
|
||||
class_type type;
|
||||
|
||||
klass_name() {
|
||||
}
|
||||
|
||||
klass_name(std::vector<std::string> namespaces
|
||||
, std::string eolian_name, qualifier_def base_qualifier
|
||||
, class_type type)
|
||||
|
@ -527,6 +530,7 @@ enum class function_type
|
|||
|
||||
struct function_def
|
||||
{
|
||||
klass_name klass;
|
||||
type_def return_type;
|
||||
std::string name;
|
||||
std::vector<parameter_def> parameters;
|
||||
|
@ -543,7 +547,8 @@ struct function_def
|
|||
|
||||
friend inline bool operator==(function_def const& lhs, function_def const& rhs)
|
||||
{
|
||||
return lhs.return_type == rhs.return_type
|
||||
return lhs.klass == rhs.klass
|
||||
&& lhs.return_type == rhs.return_type
|
||||
&& lhs.name == rhs.name
|
||||
&& lhs.parameters == rhs.parameters
|
||||
&& lhs.c_name == rhs.c_name
|
||||
|
@ -561,7 +566,8 @@ struct function_def
|
|||
return !(lhs == rhs);
|
||||
}
|
||||
function_def() = default;
|
||||
function_def(type_def _return_type, std::string const& _name,
|
||||
function_def(klass_name _klass,
|
||||
type_def _return_type, std::string const& _name,
|
||||
std::vector<parameter_def> const& _parameters,
|
||||
std::string const& _c_name,
|
||||
std::string _filename,
|
||||
|
@ -572,8 +578,9 @@ struct function_def
|
|||
bool _is_beta = false,
|
||||
bool _is_protected = false,
|
||||
Eolian_Unit const* unit = nullptr)
|
||||
: return_type(_return_type), name(_name), parameters(_parameters),
|
||||
c_name(_c_name), filename(_filename), documentation(_documentation),
|
||||
: klass(_klass), return_type(_return_type), name(_name),
|
||||
parameters(_parameters), c_name(_c_name), filename(_filename),
|
||||
documentation(_documentation),
|
||||
return_documentation(_return_documentation),
|
||||
property_documentation(_property_documentation),
|
||||
type(_type),
|
||||
|
@ -633,8 +640,10 @@ struct function_def
|
|||
c_name = eolian_function_full_c_name_get(function, type, EINA_FALSE);
|
||||
if (type != EOLIAN_FUNCTION_POINTER)
|
||||
{
|
||||
const Eolian_Class *klass = eolian_function_class_get(function);
|
||||
filename = eolian_object_file_get((const Eolian_Object *)klass);
|
||||
const Eolian_Class *eolian_klass = eolian_function_class_get(function);
|
||||
filename = eolian_object_file_get((const Eolian_Object *)eolian_klass);
|
||||
klass = klass_name(eolian_klass,
|
||||
{attributes::qualifier_info::is_none, std::string()});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -191,4 +191,21 @@ class TestEoParent
|
|||
}
|
||||
}
|
||||
|
||||
class TestKlassMethods
|
||||
{
|
||||
public static void basic_class_method()
|
||||
{
|
||||
int reference = 0xbeef;
|
||||
test.TestingConcrete.SetKlassProp(reference);
|
||||
Test.AssertEquals(reference, test.TestingConcrete.GetKlassProp());
|
||||
}
|
||||
|
||||
public static void inherited_class_method()
|
||||
{
|
||||
int reference = 0xdead;
|
||||
test.ChildConcrete.SetKlassProp(reference);
|
||||
Test.AssertEquals(reference, test.ChildConcrete.GetKlassProp());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3763,6 +3763,30 @@ void _test_testing_call_format_cb(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_
|
|||
func_free_cb(func_data);
|
||||
}
|
||||
|
||||
/* Class Properties */
|
||||
static int _test_testing_klass_prop = 0;
|
||||
|
||||
int _test_testing_klass_prop_get(Eo *klass, EINA_UNUSED void *pd)
|
||||
{
|
||||
EINA_LOG_ERR("FAIL on GET");
|
||||
if (klass != test_testing_class_get())
|
||||
{
|
||||
eina_error_set(EINVAL);
|
||||
return -1;
|
||||
}
|
||||
return _test_testing_klass_prop;
|
||||
}
|
||||
|
||||
void _test_testing_klass_prop_set(Eo *klass, EINA_UNUSED void *pd, int value)
|
||||
{
|
||||
EINA_LOG_ERR("FAIL on SET");
|
||||
if (klass != test_testing_class_get())
|
||||
{
|
||||
eina_error_set(EINVAL);
|
||||
}
|
||||
_test_testing_klass_prop = value;
|
||||
}
|
||||
|
||||
#include "test_testing.eo.c"
|
||||
#include "test_numberwrapper.eo.c"
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import eina_types;
|
||||
|
||||
class Test.Child (Test.Testing) {
|
||||
|
||||
implements {
|
||||
class.constructor;
|
||||
class.destructor;
|
||||
}
|
||||
}
|
|
@ -1583,6 +1583,14 @@ class Test.Testing (Efl.Object, Efl.Part) {
|
|||
@in func: Test.FormatCb;
|
||||
}
|
||||
}
|
||||
|
||||
@property klass_prop @class {
|
||||
get {}
|
||||
set {}
|
||||
values {
|
||||
prop: int;
|
||||
}
|
||||
}
|
||||
}
|
||||
implements {
|
||||
class.constructor;
|
||||
|
|
Loading…
Reference in New Issue