From 54778ee1e1c91e1307cd172b32abfe211418d4df Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Fri, 9 Nov 2012 19:28:27 +0100 Subject: [PATCH] Some basic C++/Nasal binding helpers - Add nasal::to_nasal for converting different C++ types to the according Nasal types. - Add nasal::Hash, an OOP wrapper around Nasal hashes. --- simgear/CMakeLists.txt | 1 + simgear/nasal/cppbind/CMakeLists.txt | 19 +++++ simgear/nasal/cppbind/NasalHash.cxx | 69 ++++++++++++++++++ simgear/nasal/cppbind/NasalHash.hxx | 97 ++++++++++++++++++++++++++ simgear/nasal/cppbind/cppbind_test.cxx | 50 +++++++++++++ simgear/nasal/cppbind/to_nasal.cxx | 50 +++++++++++++ simgear/nasal/cppbind/to_nasal.hxx | 79 +++++++++++++++++++++ 7 files changed, 365 insertions(+) create mode 100644 simgear/nasal/cppbind/CMakeLists.txt create mode 100644 simgear/nasal/cppbind/NasalHash.cxx create mode 100644 simgear/nasal/cppbind/NasalHash.hxx create mode 100644 simgear/nasal/cppbind/cppbind_test.cxx create mode 100644 simgear/nasal/cppbind/to_nasal.cxx create mode 100644 simgear/nasal/cppbind/to_nasal.hxx diff --git a/simgear/CMakeLists.txt b/simgear/CMakeLists.txt index fd83c895..b4e299ae 100644 --- a/simgear/CMakeLists.txt +++ b/simgear/CMakeLists.txt @@ -11,6 +11,7 @@ foreach( mylibfolder math misc nasal + nasal/cppbind props serial structure diff --git a/simgear/nasal/cppbind/CMakeLists.txt b/simgear/nasal/cppbind/CMakeLists.txt new file mode 100644 index 00000000..d77731a9 --- /dev/null +++ b/simgear/nasal/cppbind/CMakeLists.txt @@ -0,0 +1,19 @@ +include (SimGearComponent) + +set(HEADERS + NasalHash.hxx + to_nasal.hxx +) + +set(SOURCES + NasalHash.cxx + to_nasal.cxx +) + +simgear_component(nasal/cppbind nasal/cppbind "${SOURCES}" "${HEADERS}") + +if(ENABLE_TESTS) + add_executable(test_cppbind cppbind_test.cxx) + add_test(test_cppbind ${EXECUTABLE_OUTPUT_PATH}/test_cppbind) + target_link_libraries(test_cppbind SimGearCore) +endif(ENABLE_TESTS) \ No newline at end of file diff --git a/simgear/nasal/cppbind/NasalHash.cxx b/simgear/nasal/cppbind/NasalHash.cxx new file mode 100644 index 00000000..1595c266 --- /dev/null +++ b/simgear/nasal/cppbind/NasalHash.cxx @@ -0,0 +1,69 @@ +// Wrapper class for Nasal hashes +// +// 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 + +#include "NasalHash.hxx" +#include "to_nasal.hxx" + +#include + +namespace nasal +{ + + //---------------------------------------------------------------------------- + Hash::Hash(naContext c): + _hash( naNewHash(c) ), + _context(c) + { + + } + + //---------------------------------------------------------------------------- + Hash::Hash(const naRef& hash, naContext c): + _hash(hash), + _context(c) + { + assert( naIsHash(_hash) ); + } + + //---------------------------------------------------------------------------- + void Hash::set(const std::string& name, naRef ref) + { + naHash_set(_hash, to_nasal(_context, name), ref); + } + + //---------------------------------------------------------------------------- + Hash Hash::createHash(const std::string& name) + { + Hash hash(_context); + set(name, hash); + return hash; + } + + //---------------------------------------------------------------------------- + void Hash::setContext(naContext context) + { + _context = context; + } + + //---------------------------------------------------------------------------- + const naRef Hash::get_naRef() const + { + return _hash; + } + +} // namespace nasal diff --git a/simgear/nasal/cppbind/NasalHash.hxx b/simgear/nasal/cppbind/NasalHash.hxx new file mode 100644 index 00000000..a56c761d --- /dev/null +++ b/simgear/nasal/cppbind/NasalHash.hxx @@ -0,0 +1,97 @@ +// Wrapper class for Nasal hashes +// +// 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_NASAL_HASH_HXX_ +#define SG_NASAL_HASH_HXX_ + +#include "to_nasal.hxx" + +namespace nasal +{ + + /** + * A Nasal Hash + */ + class Hash + { + public: + + /** + * Create a new Nasal Hash + * + * @param c Nasal context for creating the hash + */ + Hash(naContext c); + + /** + * Initialize from an existing Nasal Hash + * + * @param hash Existing Nasal Hash + * @param c Nasal context for creating new Nasal objects + */ + Hash(const naRef& hash, naContext c); + + /** + * Set member + * + * @param name Member name + * @param ref Reference to Nasal object (naRef) + */ + void set(const std::string& name, naRef ref); + + /** + * Set member to anything convertible using to_nasal + * + * @param name Member name + * @param val Value (has to be convertible with to_nasal) + */ + template + void set(const std::string& name, const T& val) + { + set(name, to_nasal(_context, val)); + } + + /** + * Create a new child hash (module) + * + * @param name Name of the new hash inside this hash + */ + Hash createHash(const std::string& name); + + /** + * Set a new Nasal context. Eg. in FlightGear the context changes every + * frame, so if using the same Hash instance for multiple frames you have + * to update the context before using the Hash object. + */ + void setContext(naContext context); + + /** + * Get Nasal representation of Hash + */ + const naRef get_naRef() const; + + protected: + + naRef _hash; + naContext _context; + + }; + +} // namespace nasal + +#endif /* SG_NASAL_HASH_HXX_ */ diff --git a/simgear/nasal/cppbind/cppbind_test.cxx b/simgear/nasal/cppbind/cppbind_test.cxx new file mode 100644 index 00000000..48269a8e --- /dev/null +++ b/simgear/nasal/cppbind/cppbind_test.cxx @@ -0,0 +1,50 @@ +#include "NasalHash.hxx" + +#include +#include + +#define VERIFY(a) \ + if( !(a) ) \ + { \ + std::cerr << "failed:" << #a << std::endl; \ + return 1; \ + } + +int main(int argc, char* argv[]) +{ + naContext c = naNewContext(); + naRef r; + + using namespace nasal; + + r = to_nasal(c, "Test"); + VERIFY( strncmp("Test", naStr_data(r), naStr_len(r)) == 0 ); + + r = to_nasal(c, std::string("Test")); + VERIFY( strncmp("Test", naStr_data(r), naStr_len(r)) == 0 ); + + r = to_nasal(c, 42); + VERIFY( naNumValue(r).num == 42 ); + + r = to_nasal(c, 4.2); + VERIFY( naNumValue(r).num == 4.2 ); + + std::vector vec; + r = to_nasal(c, vec); + + Hash hash(c); + hash.set("vec", r); + hash.set("vec2", vec); + hash.set("name", "my-name"); + hash.set("string", std::string("blub")); + + r = to_nasal(c, hash); + VERIFY( naIsHash(r) ); + + Hash mod = hash.createHash("mod"); + mod.set("parent", hash); + + naFreeContext(c); + + return 0; +} diff --git a/simgear/nasal/cppbind/to_nasal.cxx b/simgear/nasal/cppbind/to_nasal.cxx new file mode 100644 index 00000000..c4a8e340 --- /dev/null +++ b/simgear/nasal/cppbind/to_nasal.cxx @@ -0,0 +1,50 @@ +// Conversion functions to convert C++ types to Nasal types +// +// 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 + +#include "to_nasal.hxx" +#include "NasalHash.hxx" + +namespace nasal +{ + //---------------------------------------------------------------------------- + naRef to_nasal(naContext c, const std::string& str) + { + naRef ret = naNewString(c); + naStr_fromdata(ret, str.c_str(), str.size()); + return ret; + } + + //---------------------------------------------------------------------------- + naRef to_nasal(naContext c, naCFunction func) + { + return naNewFunc(c, naNewCCode(c, func)); + } + + //---------------------------------------------------------------------------- + naRef to_nasal(naContext c, const Hash& hash) + { + return hash.get_naRef(); + } + + //---------------------------------------------------------------------------- + naRef to_nasal(naContext c, naRef ref) + { + return ref; + } + +} // namespace nasal diff --git a/simgear/nasal/cppbind/to_nasal.hxx b/simgear/nasal/cppbind/to_nasal.hxx new file mode 100644 index 00000000..1166a4f4 --- /dev/null +++ b/simgear/nasal/cppbind/to_nasal.hxx @@ -0,0 +1,79 @@ +// Conversion functions to convert C++ types to Nasal types +// +// 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_HXX_ +#define SG_TO_NASAL_HXX_ + +#include + +#include +#include + +#include +#include + +namespace nasal +{ + class Hash; + + /** + * Convert std::string to Nasal string + */ + naRef to_nasal(naContext c, const std::string& 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, naRef ref); + + /** + * Convert a numeric type to Nasal number + */ + template + typename boost::enable_if< boost::is_arithmetic, naRef >::type + to_nasal(naContext c, T num) + { + return naNum(num); + } + + /** + * Convert std::vector to Nasal vector + */ + template + naRef to_nasal(naContext c, const std::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(c, vec[i])); + return ret; + } + +} // namespace nasal + +#endif /* SG_TO_NASAL_HXX_ */ -- 2.39.5