efl/src/bin/eolian_mono/eolian/mono/parameter.hh

1643 lines
74 KiB
C++
Raw Normal View History

/*
* Copyright 2019 by its authors. See AUTHORS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef EOLIAN_MONO_PARAMETER_HH
#define EOLIAN_MONO_PARAMETER_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/attribute_reorder.hpp"
#include "grammar/case.hpp"
#include "helpers.hh"
#include "marshall_type.hh"
#include "type.hh"
#include "using_decl.hh"
#include "name_helpers.hh"
using namespace eolian_mono::name_helpers;
namespace eolian_mono {
struct parameter_generator;
struct marshall_parameter_generator;
struct argument_generator;
struct argument_invocation_generator;
struct native_argument_invocation_generator;
struct native_convert_in_variable_generator;
struct convert_in_variable_generator;
struct native_convert_out_variable_generator;
struct convert_out_variable_generator;
struct convert_out_assign_generator;
struct native_convert_in_ptr_assign_generator;
struct convert_in_ptr_assign_generator;
struct native_convert_out_assign_parameterized;
struct native_convert_out_assign_generator;
struct convert_return_generator;
struct convert_return_variable_generator;
struct native_convert_return_generator;
struct native_convert_return_parameterized;
struct native_convert_return_variable_generator;
struct convert_function_pointer_generator;
struct native_convert_function_pointer_generator;
struct constructor_param_generator;
struct constructor_invocation_generator;
struct constructor_parameter_name_generator;
struct constructor_parameter_name_paremeterized;
}
namespace efl { namespace eolian { namespace grammar {
template <>
struct is_eager_generator< ::eolian_mono::parameter_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::parameter_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::parameter_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::marshall_parameter_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::marshall_parameter_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::marshall_parameter_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::argument_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::argument_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::argument_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::argument_invocation_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::argument_invocation_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::argument_invocation_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::native_argument_invocation_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::native_argument_invocation_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::native_argument_invocation_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::native_convert_in_variable_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::native_convert_in_variable_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::native_convert_in_variable_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::convert_in_variable_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::convert_in_variable_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::convert_in_variable_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::convert_out_variable_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::convert_out_variable_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::convert_out_variable_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::native_convert_out_variable_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::native_convert_out_variable_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::native_convert_out_variable_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::convert_out_assign_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::convert_out_assign_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::convert_out_assign_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::native_convert_in_ptr_assign_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::native_convert_in_ptr_assign_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::native_convert_in_ptr_assign_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::convert_in_ptr_assign_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::convert_in_ptr_assign_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::convert_in_ptr_assign_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::convert_return_variable_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::convert_return_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::convert_return_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::convert_return_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::native_convert_out_assign_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::native_convert_out_assign_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::native_convert_out_assign_parameterized> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::native_convert_out_assign_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::native_convert_return_variable_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::native_convert_return_variable_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::native_convert_return_variable_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::native_convert_return_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::native_convert_return_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::native_convert_return_parameterized> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::native_convert_return_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::convert_function_pointer_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::convert_function_pointer_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::convert_function_pointer_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::native_convert_function_pointer_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::native_convert_function_pointer_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::native_convert_function_pointer_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::constructor_param_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::constructor_param_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::constructor_param_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::constructor_invocation_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::constructor_invocation_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::constructor_invocation_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::constructor_parameter_name_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::constructor_parameter_name_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::constructor_parameter_name_paremeterized> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::constructor_parameter_name_generator> : std::integral_constant<int, 1> {};
}
} } }
namespace eolian_mono {
namespace attributes = efl::eolian::grammar::attributes;
// Helper function to query parameter attributes
const static bool WANT_OWN = true;
const static bool WANT_OUT = true;
inline bool param_is_acceptable(attributes::parameter_def const &param, std::string c_type, bool want_own, bool want_out)
{
return (param.type.c_type == c_type)
&& ((param.direction != attributes::parameter_direction::in) == want_out)
&& (param.type.has_own == want_own);
}
inline bool param_should_use_out_var(attributes::parameter_def const& param, bool native)
{
if (param.direction == attributes::parameter_direction::in)
return false;
if ((native && param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT))
|| (native && param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT))
|| param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT)
)
return true;
auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
if (helpers::need_struct_conversion(regular))
return true;
if (param.type.is_ptr && helpers::need_pointer_conversion(regular))
return true;
return false;
}
inline bool param_should_use_in_var(attributes::parameter_def const& param, bool /*native*/)
{
if (param.direction != attributes::parameter_direction::in)
return false;
if (param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_Array *", !WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_Array *", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "const Eina_Array *", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_List *", !WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_List *", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "const Eina_List *", !WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "const Eina_List *", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_Hash *", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_Value", WANT_OWN, !WANT_OUT)
|| param_is_acceptable(param, "Eina_Value", !WANT_OWN, !WANT_OUT)
)
return true;
auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
if (helpers::need_struct_conversion(regular))
return true;
if (param.type.is_ptr && helpers::need_pointer_conversion(regular))
return true;
return false;
}
inline std::string out_variable_name(std::string const& param_name)
{
return "_out_" + escape_keyword(param_name);
}
inline std::string in_variable_name(std::string const& param_name)
{
return "_in_" + escape_keyword(param_name);
}
inline std::string direction_modifier(attributes::parameter_def const& param)
{
if (param.direction == attributes::parameter_direction::inout)
{
return "ref ";
}
else if (param.direction != attributes::parameter_direction::in)
{
if (param.type.c_type == "Eina_Slice" || param.type.c_type == "Eina_Rw_Slice")
return "ref ";
else
return "out ";
}
else if (param.direction == attributes::parameter_direction::in && param.type.is_ptr)
{
auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
if (helpers::need_struct_conversion(regular))
return "ref "; // Don't add ref on Marshal if it is ptr
}
return "";
}
std::string marshall_direction_modifier(attributes::parameter_def const& param)
{
if (param.direction == attributes::parameter_direction::in && param.type.is_ptr)
{
auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
if (helpers::need_struct_conversion(regular) && param.type.has_own)
return " "; // Don't add ref on Marshal if it is ptr
}
return direction_modifier(param);
}
struct is_fp_visitor
{
typedef is_fp_visitor visitor_type;
typedef bool result_type;
bool operator()(grammar::attributes::regular_type_def const &type) const
{
return type.is_function_ptr();
}
template<typename T>
bool operator()(T const &) const
{
return false;
}
};
struct type_name_visitor
{
typedef type_name_visitor visitor_type;
typedef std::string result_type;
std::string operator()(grammar::attributes::regular_type_def const &type) const
{
return name_helpers::type_full_eolian_name(type);
}
template<typename T>
std::string operator()(T const &) const
{
return "";
}
};
struct parameter_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
std::string param_name = escape_keyword(param.param_name);
return as_generator(
direction_modifier(param) << type << " " << string
).generate(sink, std::make_tuple(param, param_name), context);
}
} const parameter {};
struct marshall_parameter_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
std::string param_name = escape_keyword(param.param_name);
if (!param.type.original_type.visit(is_fp_visitor{}))
return as_generator(
marshall_direction_modifier(param) << marshall_type << " " << string
).generate(sink, std::make_tuple(param, param_name), context);
return as_generator(
"IntPtr " << param_name << "_data, " << type << "Internal " << param_name << ", Eina.Callbacks.EinaFreeCb "
<< param_name << "_free_cb"
).generate(sink, param, context);
}
} const marshall_parameter {};
// FIXME This seems to be used only in the else branch of the native function definition. Is it really needed?
struct argument_generator
{
bool generate_direction;
argument_generator () : generate_direction(true) {}
argument_generator (bool r) : generate_direction(r) {}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
std::string param_name = escape_keyword(param.param_name);
std::string direction = marshall_direction_modifier(param);
if (generate_direction && !param.type.original_type.visit(is_fp_visitor{}))
return as_generator(direction << param_name).generate(sink, attributes::unused, context);
if (!generate_direction && !param.type.original_type.visit(is_fp_visitor{}))
return as_generator(param_name).generate(sink, attributes::unused, context);
else
return as_generator
(param_name << "_data, " << param_name << ", " << param_name << "_free_cb"
).generate(sink, attributes::unused, context);
}
argument_generator operator ()(bool r) const
{
return {r};
}
} const argument {};
struct native_argument_invocation_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
std::string arg = direction_modifier(param);
if (param_should_use_out_var(param, true))
arg += out_variable_name(param.param_name);
else if (param_should_use_in_var(param, true))
arg += in_variable_name(param.param_name);
else if (param.type.original_type.visit(is_fp_visitor{}))
{
arg += escape_keyword(param.param_name) + "_wrapper.ManagedCb";
}
else // FIXME Wrap data and C function pointers into some kind of structure.
arg += escape_keyword(param.param_name);
return as_generator(arg).generate(sink, attributes::unused, context);
}
} const native_argument_invocation {};
// Generates the correct parameter name when invoking a function
struct argument_invocation_generator
{
constexpr argument_invocation_generator(bool conversion_vars)
: use_conversion_vars(conversion_vars)
{}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
std::string arg = marshall_direction_modifier(param);
if (use_conversion_vars && param_should_use_out_var(param, false))
arg += out_variable_name(param.param_name);
else if (use_conversion_vars && param_should_use_in_var(param, false))
arg += in_variable_name(param.param_name);
else if (param.type.original_type.visit(is_fp_visitor{}))
{
std::string param_name = escape_keyword(param.param_name);
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
return as_generator("GCHandle.ToIntPtr(" << param_name << "_handle), " << type << "Wrapper.Cb, Efl.Eo.Globals.free_gchandle")
.generate(sink, param.type, context);
}
else
arg += escape_keyword(param.param_name);
return as_generator(arg).generate(sink, attributes::unused, context);
}
bool const use_conversion_vars;
} const argument_invocation {true};
argument_invocation_generator const argument_invocation_no_conversion {false};
struct native_convert_in_variable_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
if (param.direction != attributes::parameter_direction::in)
return true;
auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
if (param.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(param, regular))
{
return as_generator(
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
"var " << string << " = Eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << escape_keyword(param.param_name) << ");\n"
).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
}
else if (helpers::need_struct_conversion(regular))
{
return as_generator(
type << " " << string << " = " << escape_keyword(param.param_name) << ";\n"
).generate(sink, std::make_tuple(param.type, in_variable_name(param.param_name)), context);
}
else if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *")
{
return as_generator(
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
"var " << string << " = new Eina.Binbuf(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ");\n"
).generate(sink, in_variable_name(param.param_name), context);
}
else if (param.type.c_type == "Eina_Hash *" || param.type.c_type == "const Eina_Hash *")
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex || complex->subtypes.size() != 2)
return false;
return as_generator(
"var " << string << " = new " << type << "(" << escape_keyword(param.param_name)
<< ", " << (param.type.has_own ? "true" : "false")
<< ", " << (complex->subtypes.front().has_own ? "true" : "false")
<< ", " << (complex->subtypes.back().has_own ? "true" : "false")
<< ");\n"
).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
}
else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *"
|| param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *"
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
return as_generator(
"var " << string << " = new " << type << "(" << escape_keyword(param.param_name)
<< ", " << (param.type.has_own ? "true" : "false")
<< ", " << (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own ? "true" : "false")
<< ");\n"
).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
}
else if (param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *")
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
return as_generator(
"var " << string << " = Efl.Eo.Globals.IteratorTo" << type << "(" << escape_keyword(param.param_name)
<< ");\n"
).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
}
else if (param.type.c_type == "Eina_Accessor *" || param.type.c_type == "const Eina_Accessor *")
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
return as_generator(
"var " << string << " = Efl.Eo.Globals.AccessorTo" << type << "(" << escape_keyword(param.param_name)
<< ");\n"
).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
}
else if (param.type.c_type == "Eina_Value")
{
return as_generator(
"var " << string << " = new " << type << "(" << string << ");\n"
).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type, param.param_name), context);
}
return true;
}
} const native_convert_in_variable {};
struct convert_in_variable_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
if (param.direction != attributes::parameter_direction::in)
return true;
auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
if (param.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(param, regular))
{
return as_generator(
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
"var " << string << " = Eina.PrimitiveConversion.ManagedToPointerAlloc(" << escape_keyword(param.param_name) << ");\n"
).generate(sink, in_variable_name(param.param_name), context);
}
else if (helpers::need_struct_conversion(regular))
{
return as_generator(
marshall_type << " " << string << " = " << escape_keyword(param.param_name) << ";\n"
).generate(sink, std::make_tuple(param.type, in_variable_name(param.param_name)), context);
}
else if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *")
{
auto var_name = in_variable_name(param.param_name);
if (!as_generator(
"var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n"
).generate(sink, var_name, context))
return false;
if (param.type.has_own)
{
return as_generator(
escape_keyword(param.param_name) << ".Own = false;\n"
).generate(sink, attributes::unused, context);
}
}
else if (param.type.c_type == "Eina_Hash *" || param.type.c_type == "const Eina_Hash *")
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex || complex->subtypes.size() != 2)
return false;
auto var_name = in_variable_name(param.param_name);
if (!as_generator(
"var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n"
).generate(sink, var_name, context))
return false;
if (param.type.has_own && !as_generator(
escape_keyword(param.param_name) << ".SetOwn(false);\n"
).generate(sink, attributes::unused, context))
return false;
if (complex->subtypes.front().has_own && !as_generator(
escape_keyword(param.param_name) << ".SetOwnKey(false);\n"
).generate(sink, attributes::unused, context))
return false;
if (complex->subtypes.back().has_own && !as_generator(
escape_keyword(param.param_name) << ".SetOwnValue(false);\n"
<< escape_keyword(param.param_name) << ".UnSetFreeCb();\n"
).generate(sink, attributes::unused, context))
return false;
}
else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *"
|| param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *"
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
auto var_name = in_variable_name(param.param_name);
if (!as_generator(
"var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n"
).generate(sink, var_name, context))
return false;
if (param.type.has_own && !as_generator(
escape_keyword(param.param_name) << ".Own = false;\n"
).generate(sink, attributes::unused, context))
return false;
if ((param.type.has_own && (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own))
&& !as_generator(
escape_keyword(param.param_name) << ".OwnContent = false;\n"
).generate(sink, attributes::unused, context))
return false;
}
else if (param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *")
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
auto var_name = in_variable_name(param.param_name);
if (!as_generator(
"var " << string << " = Efl.Eo.Globals.IEnumerableToIterator(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
).generate(sink, var_name, context))
return false;
}
else if (param.type.c_type == "Eina_Accessor *" || param.type.c_type == "const Eina_Accessor *")
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
auto var_name = in_variable_name(param.param_name);
if (!as_generator(
"var " << string << " = Efl.Eo.Globals.IEnumerableToAccessor(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
).generate(sink, var_name, context))
return false;
}
else if (param.type.c_type == "Eina_Value")
{
return as_generator(
"var " << string << " = " << string << ".GetNative();\n"
).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.param_name), context);
}
return true;
}
} const convert_in_variable {};
/* Some types require an intermediate variable to be filled as out parameter in the marshalled function */
struct convert_out_variable_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
if (param.direction == attributes::parameter_direction::in)
return true;
auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
if (param.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular))
{
return as_generator(
"System.IntPtr " << string << " = System.IntPtr.Zero;\n"
).generate(sink, out_variable_name(param.param_name), context);
}
else if (helpers::need_struct_conversion(regular))
{
return as_generator(
"var " << string << " = new " << marshall_type << "();\n"
).generate(sink, std::make_tuple(out_variable_name(param.param_name), param), context);
}
else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
)
{
return as_generator(
"System.IntPtr " << string << " = System.IntPtr.Zero;\n"
).generate(sink, out_variable_name(param.param_name), context);
}
else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
)
{
return as_generator(
"System.IntPtr " << string << " = System.IntPtr.Zero;\n"
).generate(sink, out_variable_name(param.param_name), context);
}
else if (param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT))
{
return as_generator(
marshall_type << " " << string << ";\n"
).generate(sink, std::make_tuple(param.type, out_variable_name(param.param_name)), context);
}
return true;
}
} const convert_out_variable {};
struct native_convert_out_variable_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
if (param.direction == attributes::parameter_direction::in)
return true;
auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
if (param.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular))
{
return as_generator(
type << " " << string << " = default(" << type << ");\n"
).generate(sink, std::make_tuple(param, out_variable_name(param.param_name), param), context);
}
else if (helpers::need_struct_conversion(regular)
|| param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT))
{
return as_generator(
type << " " << string << " = default(" << type << ");\n"
).generate(sink, std::make_tuple(param, out_variable_name(param.param_name), param), context);
}
else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
)
{
return as_generator(
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
"Eina.Binbuf " << string << " = default(Eina.Binbuf);\n"
).generate(sink, out_variable_name(param.param_name), context);
}
else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
return as_generator(
type << " " << string << " = default(" << type << ");\n"
).generate(sink, std::make_tuple(param.type, out_variable_name(param.param_name), param.type), context);
}
else if (param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT))
{
return as_generator(
string << " = default(" << marshall_type << ");\n"
<< type << " " << string << " = null;\n"
).generate(sink, std::make_tuple(param.param_name, param, param, out_variable_name(param.param_name)), context);
}
else if (param.direction == attributes::parameter_direction::out)
{
// Assign a default value to the out variable in case we end up in the catch clause.
return as_generator(
string << " = default(" << type << ");"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param), context);
}
return true;
}
} const native_convert_out_variable {};
/* Assign the Managed out variables from the marshalled intermediate ones if needed. */
struct convert_out_assign_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
if (param.direction == attributes::parameter_direction::in)
return true;
auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
if (param.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion_in_return(param.type, param.direction))
{
bool ret = as_generator(
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
string << " = Eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << out_variable_name(param.param_name) << ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context);
if (param.type.has_own)
ret = ret && as_generator(scope_tab << scope_tab << "Marshal.FreeHGlobal(" << out_variable_name(param.param_name) << ");\n"
).generate(sink, attributes::unused, context);
return ret;
}
else if (helpers::need_struct_conversion(regular))
{
return as_generator(
string << " = " << out_variable_name(param.param_name) << ";\n"
).generate(sink, escape_keyword(param.param_name), context);
}
else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
)
{
return as_generator(
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
string << " = new Eina.Binbuf(" << string << ", " << (param.type.has_own ? "true" : "false") << ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context);
}
else if (param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex || complex->subtypes.size() != 2)
return false;
return as_generator(
string << " = new " << type << "(" << string
<< ", " << (param.type.has_own ? "true" : "false")
<< ", " << (complex->subtypes.front().has_own ? "true" : "false")
<< ", " << (complex->subtypes.back().has_own ? "true" : "false")
<< ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
}
else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
return as_generator(
string << " = new " << type << "(" << string
<< ", " << (param.type.has_own ? "true" : "false")
<< ", " << (param.type.has_own && (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own) ? "true" : "false")
<< ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
}
else if (param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, WANT_OUT)
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
return as_generator(
string << " = Efl.Eo.Globals.AccessorTo" << type << "(" << string
<< ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
}
else if (param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
return as_generator(
string << " = Efl.Eo.Globals.IteratorTo" << type << "(" << string
<< ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
}
else if (param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT))
{
return as_generator(
string << " = new " << type << "(" << string << ");\n"
).generate(sink, std::make_tuple(param.param_name, param.type, out_variable_name(param.param_name)), context);
}
return true;
}
} const convert_out_assign {};
struct native_convert_in_ptr_assign_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
if (param_should_use_in_var(param, true) && param.type.is_ptr && !param.type.has_own && helpers::need_struct_conversion(regular))
{
return as_generator(
string << " = " << in_variable_name(param.param_name) << ";\n"
).generate(sink, escape_keyword(param.param_name), context);
}
return true;
}
} const native_convert_in_ptr_assign {};
struct convert_in_ptr_assign_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
if (param_should_use_in_var(param, true) && param.type.is_ptr && !param.type.has_own && helpers::need_struct_conversion(regular))
{
return as_generator(
string << " = " << in_variable_name(param.param_name) << ";\n"
).generate(sink, escape_keyword(param.param_name), context);
}
return true;
}
} const convert_in_ptr_assign {};
struct convert_return_variable_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
{
if (ret_type.c_type != "void")
return as_generator("var _ret_var = ").generate(sink, attributes::unused, context);
return true;
}
} const convert_return_variable {};
/* Converts the intermediate return variable to the proper API type */
struct convert_return_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
{
auto regular = efl::eina::get<attributes::regular_type_def>(&ret_type.original_type);
if (ret_type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion_in_return(ret_type, attributes::parameter_direction::unknown))
{
return as_generator(
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
"var __ret_tmp = Eina.PrimitiveConversion.PointerToManaged<" << type << ">(_ret_var);\n"
<< scope_tab << scope_tab << (ret_type.has_own ? ("Marshal.FreeHGlobal(_ret_var);\n"): "\n")
<< scope_tab << scope_tab << "return __ret_tmp;\n"
).generate(sink, ret_type, context);
}
else if (helpers::need_struct_conversion(regular))
{
return as_generator(
"return _ret_var;"
).generate(sink, nullptr, context);
}
else if (ret_type.c_type == "Eina_Binbuf *" || ret_type.c_type == "const Eina_Binbuf *")
{
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
if (!as_generator("var _binbuf_ret = new Eina.Binbuf(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"} << ");\n"
<< scope_tab << scope_tab << "return _binbuf_ret;\n")
.generate(sink, attributes::unused, context))
return false;
}
else if (ret_type.c_type == "Eina_Hash *" || ret_type.c_type == "const Eina_Hash *")
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
if (!complex || complex->subtypes.size() != 2)
return false;
if (!as_generator("return new " << type << "(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"}
<< ", " << (complex->subtypes.front().has_own ? "true" : "false")
<< ", " << (complex->subtypes.back().has_own ? "true" : "false")
<< ");\n")
.generate(sink, ret_type, context))
return false;
}
else if (ret_type.c_type == "Eina_Array *" || ret_type.c_type == "const Eina_Array *"
|| ret_type.c_type == "Eina_List *" || ret_type.c_type == "const Eina_List *"
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
if (!complex)
return false;
if (!as_generator("return new " << type << "(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"}
<< ", " << (ret_type.has_own && (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own) ? "true" : "false")
<< ");\n")
.generate(sink, ret_type, context))
return false;
}
else if (ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *")
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
if (!complex)
return false;
if (!as_generator("return Efl.Eo.Globals.AccessorTo" << type << "(_ret_var);")
.generate(sink, ret_type, context))
return false;
}
else if (ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *")
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
if (!complex)
return false;
if (!as_generator("return Efl.Eo.Globals.IteratorTo" << type << "(_ret_var);")
.generate(sink, ret_type, context))
return false;
}
else if (ret_type.c_type != "void")
{
return as_generator("return _ret_var;").generate(sink, ret_type, context);
}
return true;
}
} const convert_return {};
// Native (virtual wrappers) generators
struct native_convert_out_assign_generator
{
attributes::klass_def const* klass;
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_convert_out_assign_generator: " << param.param_name << std::endl;
if (param.direction == attributes::parameter_direction::in)
return true;
auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
if (param.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion_in_return(param.type, param.direction))
{
return as_generator(
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
string << " = Eina.PrimitiveConversion.ManagedToPointerAlloc(" << string << ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context);
}
else if (helpers::need_struct_conversion(regular))
{
return as_generator(
string << " = " << string << ";\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context);
}
else if (param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT))
{
if (klass == nullptr)
{
EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Null class found when trying to assign out stringshare from native wrapper." << std::endl;
return false;
}
return as_generator(
string << "= " << string << ";\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context);
}
else if (param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT))
{
if (klass == nullptr)
{
EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Null class found when trying to assign out string from native wrapper." << std::endl;
return false;
}
return as_generator(
string << " = " << string << ";\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context);
}
else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
)
{
if (!as_generator(
string << " = " << string << ".Handle;\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context))
return false;
if (param.type.has_own)
return as_generator(
string << ".Own = false;\n"
).generate(sink, out_variable_name(param.param_name), context);
}
else if (param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex || complex->subtypes.size() != 2)
return false;
auto outvar = out_variable_name(param.param_name);
if (!as_generator(
string << " = " << string << ".Handle;\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
return false;
if (param.type.has_own && !as_generator(
string << ".SetOwn(false);\n"
).generate(sink, outvar, context))
return false;
if (complex->subtypes.front().has_own && !as_generator(
string << ".SetOwnKey(false);\n"
).generate(sink, outvar, context))
return false;
if (complex->subtypes.back().has_own && !as_generator(
string << ".SetOwnValue(false);\n"
<< string << ".UnSetFreeCb();\n"
).generate(sink, std::make_tuple(outvar, outvar), context))
return false;
}
else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
auto outvar = out_variable_name(param.param_name);
if (!as_generator(
string << " = " << string << ".Handle;\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
return false;
if (param.type.has_own && !as_generator(
string << ".Own = false;\n"
).generate(sink, outvar, context))
return false;
if ((param.type.has_own && (complex->subtypes.front().is_value_type && complex->subtypes.front().has_own))
&& !as_generator(
string << ".OwnContent = false;\n"
).generate(sink, outvar, context))
return false;
}
else if (param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, WANT_OUT)
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
auto outvar = out_variable_name(param.param_name);
if (!as_generator(
string << " = Efl.Eo.Globals.IEnumerableToAccessor(" << string << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
return false;
}
else if (param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
|| param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
if (!complex)
return false;
auto outvar = out_variable_name(param.param_name);
if (!as_generator(
string << " = Efl.Eo.Globals.IEnumerableToIterator(" << string << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
return false;
}
return true;
}
};
struct native_convert_return_variable_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
{
if (ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *" ||
ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *")
return as_generator(
type << " _ret_var = null;"
).generate(sink, ret_type, context);
else if (ret_type.c_type != "void")
return as_generator(
type << " _ret_var = default(" << type << ");"
).generate(sink, std::make_tuple(ret_type, ret_type), context);
return true;
}
} const native_convert_return_variable {};
struct native_convert_return_generator
{
attributes::klass_def const* klass;
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
{
auto regular = efl::eina::get<attributes::regular_type_def>(&ret_type.original_type);
if (ret_type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion_in_return(ret_type, attributes::parameter_direction::unknown) )
{
return as_generator(
"return Eina.PrimitiveConversion.ManagedToPointerAlloc(_ret_var);"
).generate(sink, attributes::unused, context);
}
else if (helpers::need_struct_conversion(regular))
{
return as_generator(
"return _ret_var;"
).generate(sink, nullptr, context);
}
else if (ret_type.c_type == "const char *")
{
if(!ret_type.has_own)
{
if (klass == nullptr)
{
EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Null class found when trying to return string from native wrapper." << std::endl;
return false;
}
return as_generator(
"return _ret_var;"
).generate(sink, attributes::unused, context);
}
else
{
return as_generator("return _ret_var;"
).generate(sink, attributes::unused, context);
}
}
else if (ret_type.c_type == "Eina_Stringshare *") { // Correct check for string?
if (!ret_type.has_own)
{
if (klass == nullptr)
{
EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Null class found when trying to return stringshare from native wrapper." << std::endl;
return false;
}
return as_generator(
"return _ret_var;"
).generate(sink, attributes::unused, context);
}
else
{
return as_generator("return _ret_var;")
.generate(sink, attributes::unused, context);
}
}
else if (ret_type.c_type == "Eina_Binbuf *" || ret_type.c_type == "const Eina_Binbuf *")
{
if (ret_type.has_own && !as_generator("_ret_var.Own = false; ")
.generate(sink, attributes::unused, context))
return false;
return as_generator("return _ret_var.Handle;")
.generate(sink, attributes::unused, context);
}
else if (ret_type.c_type == "Eina_Hash *" || ret_type.c_type == "const Eina_Hash *")
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
if (!complex || complex->subtypes.size() != 2)
return false;
if (ret_type.has_own && !as_generator("_ret_var.SetOwn(false); ")
.generate(sink, attributes::unused, context))
return false;
if (complex->subtypes.front().has_own && !as_generator("_ret_var.SetOwnKey(false); ")
.generate(sink, attributes::unused, context))
return false;
if (complex->subtypes.back().has_own && !as_generator("_ret_var.SetOwnValue(false); _ret_var.UnSetFreeCb(); ")
.generate(sink, attributes::unused, context))
return false;
return as_generator("return _ret_var.Handle;")
.generate(sink, attributes::unused, context);
}
else if (ret_type.c_type == "Eina_Array *" || ret_type.c_type == "const Eina_Array *"
|| ret_type.c_type == "Eina_List *" || ret_type.c_type == "const Eina_List *"
)
{
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
if (!complex)
return false;
if (ret_type.has_own && !as_generator("_ret_var.Own = false; ")
.generate(sink, attributes::unused, context))
return false;
return as_generator("return _ret_var.Handle;")
.generate(sink, attributes::unused, context);
}
else if (ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *")
{
return as_generator(lit("return Efl.Eo.Globals.IEnumerableToAccessor(_ret_var, ") << (ret_type.has_own ? "true" : "false") << ");")
.generate(sink, attributes::unused, context);
}
else if (ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *")
{
return as_generator(lit("return Efl.Eo.Globals.IEnumerableToIterator(_ret_var, ") << (ret_type.has_own ? "true" : "false") << ");")
.generate(sink, attributes::unused, context);
}
else if (ret_type.c_type != "void")
return as_generator("return _ret_var;").generate(sink, ret_type, context);
return true;
}
};
struct native_convert_out_assign_parameterized
{
native_convert_out_assign_generator const operator()(attributes::klass_def const &klass) const
{
return {&klass};
}
} const native_convert_out_assign;
struct native_convert_return_parameterized
{
native_convert_return_generator const operator()(attributes::klass_def const &klass) const
{
return {&klass};
}
} const native_convert_return;
struct convert_function_pointer_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
if (param.direction != attributes::parameter_direction::in)
return true;
if (!param.type.original_type.visit(is_fp_visitor{}))
return true;
std::string param_name = escape_keyword(param.param_name);
// Allocate GCHandle in "param_name"_handle for param;
if (!as_generator(
"GCHandle " << param_name << "_handle = GCHandle.Alloc(" << param_name << ");\n"
).generate(sink, attributes::unused, context))
return false;
return true;
}
} const convert_function_pointer {};
struct native_convert_function_pointer_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
if (param.direction != attributes::parameter_direction::in)
return true;
if (!param.type.original_type.visit(is_fp_visitor{}))
return true;
// Getting the type through C api
std::string type_name = param.type.original_type.visit(type_name_visitor{});
const Eolian_Typedecl *tpd = ::eolian_unit_alias_by_name_get(param.unit, type_name.c_str());
if (!tpd)
{
EINA_LOG_ERR("Failed to get typedecl for c type [%s]", param.type.c_type.c_str());
return false;
}
if (eolian_typedecl_type_get(tpd) != EOLIAN_TYPEDECL_FUNCTION_POINTER)
return true;
const Eolian_Function *fd = eolian_typedecl_function_pointer_get(tpd);
if (!fd)
{
EINA_LOG_ERR("Failed to get function pointer info for c type [%s]", param.type.c_type.c_str());
return false;
}
attributes::function_def f(fd, EOLIAN_FUNCTION_POINTER, tpd, param.unit);
std::string param_name = escape_keyword(param.param_name);
// Allocate GCHandle in "param_name"_handle for param;
if (!as_generator(
scope_tab << type << "Wrapper " << param_name << "_wrapper = new " << type << "Wrapper("
<< param_name << ", " << param_name << "_data, " << param_name << "_free_cb);\n"
).generate(sink, std::make_tuple(param.type, param.type), context))
return false;
// FIXME What about calling the free function?
return true;
}
} const native_convert_function_pointer {};
struct constructor_parameter_name_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
auto target_name = name_helpers::constructor_managed_name(ctor.name);
// Only multi-valued constructing methods get their actual parameter names
if (ctor.function.parameters.size() > 1)
target_name += '_' + param.param_name;
auto name = name_helpers::managed_name(target_name);
name[0] = std::tolower(name[0]);
return as_generator(string).generate(sink, name, context);
}
attributes::constructor_def const& ctor;
};
struct constructor_parameter_name_parameterized
{
constructor_parameter_name_generator const operator()(attributes::constructor_def const& ctor) const
{
return {ctor};
}
} const constructor_parameter_name;
// Generates the parameters for the given constructor
// If the constructor receives multiple parameters, they get the name
// of the constructor plus the name of the parameter (e.g. DefineParentData, DefineIndex)
struct constructor_param_generator
{
template<typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context const& context) const
{
auto params = ctor.function.parameters;
if (!as_generator(
efl::eolian::grammar::attribute_reorder<1, -1>
(type(false, ctor.is_optional) << " " << constructor_parameter_name(ctor) << (ctor.is_optional ? " = null" : "")) % ", "
).generate(sink, params, context))
return false;
// }
return true;
}
} const constructor_param;
// Generates the invocation of the given parameter
struct constructor_invocation_generator
{
template<typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context const& context) const
{
auto params = ctor.function.parameters;
if (!as_generator(
"if (" <<
(efl::eolian::grammar::attribute_reorder<-1>
("Efl.Eo.Globals.ParamHelperCheck(" << constructor_parameter_name(ctor) << ")") % " || ") << ")\n"
<< scope_tab << scope_tab << "{\n"
<< scope_tab << scope_tab << scope_tab << name_helpers::managed_method_name(ctor.function) << "("
).generate(sink, params, context))
return false;
size_t idx = 0;
for (auto&& param : params)
{
idx++;
if (!as_generator(
"Efl.Eo.Globals.GetParamHelper(" << constructor_parameter_name(ctor) << ")" << ((idx < params.size()) ? ", " : "")
).generate(sink, param, context))
return false;
}
if (!as_generator(
");\n"
<< scope_tab << scope_tab << "}\n").generate(sink, attributes::unused, context))
return false;
return true;
}
} const constructor_invocation;
}
#endif