From ceae2928aab1ce54412e8f45af93d57b1147bee5 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Sun, 3 Mar 2013 23:39:26 +0100 Subject: [PATCH] cppbind: refactor to_nasal for better name lookup. Using template parameter dependent name lookup it is now possible to create to_nasal_helper overloads for custom types and having them used for automatic type conversion with binding methods/member on nasal::Ghost objects. --- simgear/nasal/cppbind/CMakeLists.txt | 9 +- simgear/nasal/cppbind/cppbind_test.cxx | 12 +- .../from_nasal_helper.cxx} | 6 +- .../from_nasal_helper.hxx} | 6 +- .../cppbind/{ => detail}/nasal_traits.hxx | 0 .../to_nasal_helper.cxx} | 20 +-- .../nasal/cppbind/detail/to_nasal_helper.hxx | 163 ++++++++++++++++++ simgear/nasal/cppbind/from_nasal.hxx | 2 +- simgear/nasal/cppbind/to_nasal.hxx | 146 ++-------------- 9 files changed, 212 insertions(+), 152 deletions(-) rename simgear/nasal/cppbind/{from_nasal.cxx => detail/from_nasal_helper.cxx} (95%) rename simgear/nasal/cppbind/{from_nasal_detail.hxx => detail/from_nasal_helper.hxx} (97%) rename simgear/nasal/cppbind/{ => detail}/nasal_traits.hxx (100%) rename simgear/nasal/cppbind/{to_nasal.cxx => detail/to_nasal_helper.cxx} (76%) create mode 100644 simgear/nasal/cppbind/detail/to_nasal_helper.hxx diff --git a/simgear/nasal/cppbind/CMakeLists.txt b/simgear/nasal/cppbind/CMakeLists.txt index ed8272fd..0439e6ed 100644 --- a/simgear/nasal/cppbind/CMakeLists.txt +++ b/simgear/nasal/cppbind/CMakeLists.txt @@ -4,21 +4,22 @@ set(HEADERS Ghost.hxx NasalHash.hxx NasalString.hxx - from_nasal_detail.hxx from_nasal.hxx - nasal_traits.hxx to_nasal.hxx ) set(DETAIL_HEADERS + detail/from_nasal_helper.hxx detail/functor_templates.hxx + detail/nasal_traits.hxx + detail/to_nasal_helper.hxx ) set(SOURCES NasalHash.cxx NasalString.cxx - from_nasal.cxx - to_nasal.cxx + detail/from_nasal_helper.cxx + detail/to_nasal_helper.cxx ) simgear_component(nasal/cppbind nasal/cppbind "${SOURCES}" "${HEADERS}") diff --git a/simgear/nasal/cppbind/cppbind_test.cxx b/simgear/nasal/cppbind/cppbind_test.cxx index 90bbf855..9508ca5d 100644 --- a/simgear/nasal/cppbind/cppbind_test.cxx +++ b/simgear/nasal/cppbind/cppbind_test.cxx @@ -50,18 +50,21 @@ struct DoubleDerived: { }; + +typedef boost::shared_ptr BasePtr; + struct DoubleDerived2: public Derived { - + const BasePtr& getBase() const{return _base;} + BasePtr _base; }; -typedef boost::shared_ptr BasePtr; typedef boost::shared_ptr DerivedPtr; typedef boost::shared_ptr DoubleDerivedPtr; typedef boost::shared_ptr DoubleDerived2Ptr; -naRef to_nasal(naContext c, const BasePtr& base) +naRef to_nasal_helper(naContext c, const BasePtr& base) { return nasal::Ghost::create(c, base); } @@ -159,7 +162,8 @@ int main(int argc, char* argv[]) Ghost::init("DoubleDerivedPtr") .bases(); Ghost::init("DoubleDerived2Ptr") - .bases< Ghost >(); + .bases< Ghost >() + .member("base", &DoubleDerived2::getBase); BasePtr d( new Derived ); naRef derived = Ghost::create(c, d); diff --git a/simgear/nasal/cppbind/from_nasal.cxx b/simgear/nasal/cppbind/detail/from_nasal_helper.cxx similarity index 95% rename from simgear/nasal/cppbind/from_nasal.cxx rename to simgear/nasal/cppbind/detail/from_nasal_helper.cxx index bed08e42..a094e4fb 100644 --- a/simgear/nasal/cppbind/from_nasal.cxx +++ b/simgear/nasal/cppbind/detail/from_nasal_helper.cxx @@ -16,9 +16,9 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -#include "from_nasal_detail.hxx" -#include "NasalHash.hxx" -#include "NasalString.hxx" +#include "from_nasal_helper.hxx" +#include +#include #include diff --git a/simgear/nasal/cppbind/from_nasal_detail.hxx b/simgear/nasal/cppbind/detail/from_nasal_helper.hxx similarity index 97% rename from simgear/nasal/cppbind/from_nasal_detail.hxx rename to simgear/nasal/cppbind/detail/from_nasal_helper.hxx index 6ff72f25..865bc8d1 100644 --- a/simgear/nasal/cppbind/from_nasal_detail.hxx +++ b/simgear/nasal/cppbind/detail/from_nasal_helper.hxx @@ -17,8 +17,8 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -#ifndef SG_FROM_NASAL_DETAIL_HXX_ -#define SG_FROM_NASAL_DETAIL_HXX_ +#ifndef SG_FROM_NASAL_HELPER_HXX_ +#define SG_FROM_NASAL_HELPER_HXX_ #include "nasal_traits.hxx" @@ -145,4 +145,4 @@ namespace nasal } // namespace nasal -#endif /* SG_FROM_NASAL_DETAIL_HXX_ */ +#endif /* SG_FROM_NASAL_HELPER_HXX_ */ diff --git a/simgear/nasal/cppbind/nasal_traits.hxx b/simgear/nasal/cppbind/detail/nasal_traits.hxx similarity index 100% rename from simgear/nasal/cppbind/nasal_traits.hxx rename to simgear/nasal/cppbind/detail/nasal_traits.hxx diff --git a/simgear/nasal/cppbind/to_nasal.cxx b/simgear/nasal/cppbind/detail/to_nasal_helper.cxx similarity index 76% rename from simgear/nasal/cppbind/to_nasal.cxx rename to simgear/nasal/cppbind/detail/to_nasal_helper.cxx index b5224ad2..bc1f25e2 100644 --- a/simgear/nasal/cppbind/to_nasal.cxx +++ b/simgear/nasal/cppbind/detail/to_nasal_helper.cxx @@ -16,15 +16,15 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -#include "to_nasal.hxx" -#include "NasalHash.hxx" +#include "to_nasal_helper.hxx" +#include #include namespace nasal { //---------------------------------------------------------------------------- - naRef to_nasal(naContext c, const std::string& str) + naRef to_nasal_helper(naContext c, const std::string& str) { naRef ret = naNewString(c); naStr_fromdata(ret, str.c_str(), str.size()); @@ -32,32 +32,32 @@ namespace nasal } //---------------------------------------------------------------------------- - naRef to_nasal(naContext c, const char* str) + naRef to_nasal_helper(naContext c, const char* str) { - return to_nasal(c, std::string(str)); + return to_nasal_helper(c, std::string(str)); } //---------------------------------------------------------------------------- - naRef to_nasal(naContext c, naCFunction func) + naRef to_nasal_helper(naContext c, naCFunction func) { return naNewFunc(c, naNewCCode(c, func)); } //---------------------------------------------------------------------------- - naRef to_nasal(naContext c, const Hash& hash) + naRef to_nasal_helper(naContext c, const Hash& hash) { return hash.get_naRef(); } //---------------------------------------------------------------------------- - naRef to_nasal(naContext c, const naRef& ref) + naRef to_nasal_helper(naContext c, const naRef& ref) { return ref; } //---------------------------------------------------------------------------- - naRef to_nasal(naContext c, const SGPath& path) + naRef to_nasal_helper(naContext c, const SGPath& path) { - return to_nasal(c, path.str()); + return to_nasal_helper(c, path.str()); } } // namespace nasal diff --git a/simgear/nasal/cppbind/detail/to_nasal_helper.hxx b/simgear/nasal/cppbind/detail/to_nasal_helper.hxx new file mode 100644 index 00000000..e367e00d --- /dev/null +++ b/simgear/nasal/cppbind/detail/to_nasal_helper.hxx @@ -0,0 +1,163 @@ +///@file +/// Conversion helpers used by to_nasal(naContext, T) +/// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef SG_TO_NASAL_HELPER_HXX_ +#define SG_TO_NASAL_HELPER_HXX_ + +#include "nasal_traits.hxx" + +#include + +#include +#include +#include + +#include +#include +#include + +class SGPath; + +namespace nasal +{ + class Hash; + + /** + * Convert std::string to Nasal string + */ + naRef to_nasal_helper(naContext c, const std::string& str); + + /** + * Convert C-string to Nasal string + */ + // We need this to prevent the array overload of to_nasal being called + naRef to_nasal_helper(naContext c, const char* str); + + /** + * Convert function pointer to Nasal function + */ + naRef to_nasal_helper(naContext c, naCFunction func); + + /** + * Convert a nasal::Hash to a Nasal hash + */ + naRef to_nasal_helper(naContext c, const Hash& hash); + + /** + * Simple pass-through of naRef types to allow generic usage of to_nasal + */ + naRef to_nasal_helper(naContext c, const naRef& ref); + + naRef to_nasal_helper(naContext c, const SGPath& path); + + /** + * Convert a numeric type to Nasal number + */ + template + typename boost::enable_if< boost::is_arithmetic, naRef >::type + to_nasal_helper(naContext c, T num) + { + return naNum(num); + } + + /** + * Convert a 2d vector to Nasal vector with 2 elements + */ + template + typename boost::enable_if, naRef>::type + to_nasal_helper(naContext c, const Vec2& vec); + + /** + * Convert a std::map to a Nasal Hash + */ + template + naRef to_nasal_helper(naContext c, const std::map& map); + + /** + * Convert a fixed size array to a Nasal vector + */ + template + naRef to_nasal_helper(naContext c, const T(&array)[N]); + + /** + * Convert std::vector to Nasal vector + */ + template< template class Vector, + class T, + class Alloc + > + typename boost::enable_if< boost::is_same< Vector, + std::vector + >, + naRef + >::type + to_nasal_helper(naContext c, const Vector& vec) + { + naRef ret = naNewVector(c); + naVec_setsize(c, ret, vec.size()); + for(size_t i = 0; i < vec.size(); ++i) + naVec_set(ret, i, to_nasal_helper(c, vec[i])); + return ret; + } + + //---------------------------------------------------------------------------- + template + typename boost::enable_if, naRef>::type + to_nasal_helper(naContext c, const Vec2& vec) + { + // We take just double because in Nasal every number is represented as + // double + double nasal_vec[2] = {vec[0], vec[1]}; + return to_nasal_helper(c, nasal_vec); + } + + //---------------------------------------------------------------------------- + template + naRef to_nasal_helper(naContext c, const std::map& map) + { + naRef hash = naNewHash(c); + + typedef typename boost::call_traits::param_type param_type; + typedef typename std::map::const_iterator map_iterator; + + for( map_iterator it = map.begin(); it != map.end(); ++it ) + naHash_set + ( + hash, + to_nasal_helper(c, it->first), + to_nasal_helper(c, static_cast(it->second)) + ); + + return hash; + } + + //---------------------------------------------------------------------------- + template + naRef to_nasal_helper(naContext c, const T(&array)[N]) + { + naRef ret = naNewVector(c); + naVec_setsize(c, ret, N); + for(size_t i = 0; i < N; ++i) + naVec_set(ret, i, to_nasal_helper(c, array[i])); + return ret; + } + +} // namespace nasal + +#endif /* SG_TO_NASAL_HELPER_HXX_ */ diff --git a/simgear/nasal/cppbind/from_nasal.hxx b/simgear/nasal/cppbind/from_nasal.hxx index de152135..fe672c01 100644 --- a/simgear/nasal/cppbind/from_nasal.hxx +++ b/simgear/nasal/cppbind/from_nasal.hxx @@ -20,7 +20,7 @@ #ifndef SG_FROM_NASAL_HXX_ #define SG_FROM_NASAL_HXX_ -#include "from_nasal_detail.hxx" +#include namespace nasal { diff --git a/simgear/nasal/cppbind/to_nasal.hxx b/simgear/nasal/cppbind/to_nasal.hxx index eeaf5a97..8d1437d1 100644 --- a/simgear/nasal/cppbind/to_nasal.hxx +++ b/simgear/nasal/cppbind/to_nasal.hxx @@ -20,100 +20,35 @@ #ifndef SG_TO_NASAL_HXX_ #define SG_TO_NASAL_HXX_ -#include "nasal_traits.hxx" - -#include - -#include -#include -#include - -#include -#include -#include - -class SGPath; +#include namespace nasal { - class Hash; - - /** - * Convert std::string to Nasal string - */ - naRef to_nasal(naContext c, const std::string& str); - - /** - * Convert C-string to Nasal string - */ - // We need this to prevent the array overload of to_nasal being called - naRef to_nasal(naContext c, const char* str); - - /** - * Convert function pointer to Nasal function - */ - naRef to_nasal(naContext c, naCFunction func); - - /** - * Convert a nasal::Hash to a Nasal hash - */ - naRef to_nasal(naContext c, const Hash& hash); - - /** - * Simple pass-through of naRef types to allow generic usage of to_nasal - */ - naRef to_nasal(naContext c, const naRef& ref); - - naRef to_nasal(naContext c, const SGPath& path); - /** - * Convert a numeric type to Nasal number + * Convert any supported C++ type to Nasal. + * + * @param c Active Nasal context + * @param arg C++ Object to be converted + * @tparam T Type of converted object + * + * @throws bad_nasal_cast if conversion is not possible + * + * @note Every type which should be supported needs a function with the + * following signature declared (Type needs to be a const reference + * for non-integral types): + * + * naRef to_nasal_helper(naContext, Type) */ template - typename boost::enable_if< boost::is_arithmetic, naRef >::type - to_nasal(naContext c, T num) + naRef to_nasal(naContext c, T arg) { - return naNum(num); + return to_nasal_helper(c, arg); } - /** - * Convert a 2d vector to Nasal vector with 2 elements - */ - template - typename boost::enable_if, naRef>::type - to_nasal(naContext c, const Vec2& vec); - - /** - * Convert a std::map to a Nasal Hash - */ - template - naRef to_nasal(naContext c, const std::map& map); - - /** - * Convert a fixed size array to a Nasal vector - */ template - naRef to_nasal(naContext c, const T(&array)[N]); - - /** - * Convert std::vector to Nasal vector - */ - template< template class Vector, - class T, - class Alloc - > - typename boost::enable_if< boost::is_same< Vector, - std::vector - >, - naRef - >::type - to_nasal(naContext c, const Vector& vec) + naRef to_nasal(naContext c, const T(&array)[N]) { - naRef ret = naNewVector(c); - naVec_setsize(c, ret, vec.size()); - for(size_t i = 0; i < vec.size(); ++i) - naVec_set(ret, i, to_nasal(c, vec[i])); - return ret; + return to_nasal_helper(c, array); } /** @@ -128,52 +63,9 @@ namespace nasal static type get() { - return static_cast(&to_nasal); + return &to_nasal; } }; - - //---------------------------------------------------------------------------- - template - typename boost::enable_if, naRef>::type - to_nasal(naContext c, const Vec2& vec) - { - // We take just double because in Nasal every number is represented as - // double - double nasal_vec[2] = {vec[0], vec[1]}; - return to_nasal(c, nasal_vec); - } - - //---------------------------------------------------------------------------- - template - naRef to_nasal(naContext c, const std::map& map) - { - naRef hash = naNewHash(c); - - typedef typename boost::call_traits::param_type param_type; - typedef typename std::map::const_iterator map_iterator; - - for( map_iterator it = map.begin(); it != map.end(); ++it ) - naHash_set - ( - hash, - to_nasal(c, it->first), - to_nasal(c, static_cast(it->second)) - ); - - return hash; - } - - //---------------------------------------------------------------------------- - template - naRef to_nasal(naContext c, const T(&array)[N]) - { - naRef ret = naNewVector(c); - naVec_setsize(c, ret, N); - for(size_t i = 0; i < N; ++i) - naVec_set(ret, i, to_nasal(c, array[i])); - return ret; - } - } // namespace nasal #endif /* SG_TO_NASAL_HXX_ */ -- 2.39.5