]> git.mxchange.org Git - simgear.git/commitdiff
cppbind: allow adding free functions accepting nasal::CallContext and do some cleanup
authorThomas Geymayer <tomgey@gmail.com>
Wed, 6 Mar 2013 16:00:38 +0000 (17:00 +0100)
committerThomas Geymayer <tomgey@gmail.com>
Wed, 6 Mar 2013 16:00:38 +0000 (17:00 +0100)
simgear/nasal/cppbind/CMakeLists.txt
simgear/nasal/cppbind/Ghost.hxx
simgear/nasal/cppbind/NasalCallContext.hxx [new file with mode: 0644]
simgear/nasal/cppbind/cppbind_test.cxx
simgear/nasal/cppbind/detail/to_nasal_helper.cxx
simgear/nasal/cppbind/detail/to_nasal_helper.hxx

index 0439e6ed6e6784cbfee66819aa6147f196710c81..32a089046651483fe9d346a8be774f47252438d8 100644 (file)
@@ -2,6 +2,7 @@ include (SimGearComponent)
 
 set(HEADERS
   Ghost.hxx
+  NasalCallContext.hxx
   NasalHash.hxx
   NasalString.hxx
   from_nasal.hxx
index 4c185a2c13c81b3aaa52f7abd5d6bf6275089e58..7354644a544e3959ffdeb66d4c84e4238f0ee438 100644 (file)
@@ -20,8 +20,7 @@
 #ifndef SG_NASAL_GHOST_HXX_
 #define SG_NASAL_GHOST_HXX_
 
-#include "from_nasal.hxx"
-#include "to_nasal.hxx"
+#include "NasalCallContext.hxx"
 
 #include <simgear/debug/logstream.hxx>
 
@@ -122,120 +121,20 @@ namespace nasal
 
     BOOST_MPL_HAS_XXX_TRAIT_DEF(element_type)
 
+    template<class T>
+    struct reduced_type
+    {
+      typedef typename boost::remove_cv<
+        typename boost::remove_reference<T>::type
+      >::type type;
+    };
+
     template<class T1, class T2>
     struct reduced_is_same:
-      public boost::is_same<
-               typename boost::remove_cv<
-                 typename boost::remove_reference<T1>::type
-               >::type,
-               T2
-             >
+      public boost::is_same<typename reduced_type<T1>::type, T2>
     {};
   }
 
-  /**
-   * Context passed to a function/method being called from Nasal
-   */
-  struct CallContext
-  {
-    CallContext(naContext c, size_t argc, naRef* args):
-      c(c),
-      argc(argc),
-      args(args)
-    {}
-
-    bool isNumeric(size_t index) const
-    {
-      return (index < argc && naIsNum(args[index]));
-    }
-
-    bool isString(size_t index) const
-    {
-      return (index < argc && naIsString(args[index]));
-    }
-
-    bool isHash(size_t index) const
-    {
-      return (index < argc && naIsHash(args[index]));
-    }
-
-    bool isVector(size_t index) const
-    {
-      return (index < argc && naIsVector(args[index]));
-    }
-
-    bool isGhost(size_t index) const
-    {
-      return (index < argc && naIsGhost(args[index]));
-    }
-
-    void popFront(size_t num = 1)
-    {
-      if( argc < num )
-        return;
-
-      args += num;
-      argc -= num;
-    }
-
-    void popBack(size_t num = 1)
-    {
-      if( argc < num )
-        return;
-
-      argc -= num;
-    }
-
-    /**
-     * Get the argument with given index if it exists. Otherwise returns the
-     * passed default value.
-     *
-     * @tparam T    Type of argument (converted using ::from_nasal)
-     * @param index Index of requested argument
-     * @param def   Default value returned if too few arguments available
-     */
-    template<class T>
-    typename from_nasal_ptr<T>::return_type
-    getArg(size_t index, const T& def = T()) const
-    {
-      if( index >= argc )
-        return def;
-
-      return from_nasal<T>(args[index]);
-    }
-
-    /**
-     * Get the argument with given index. Raises a Nasal runtime error if there
-     * are to few arguments available.
-     */
-    template<class T>
-    typename from_nasal_ptr<T>::return_type
-    requireArg(size_t index) const
-    {
-      if( index >= argc )
-        naRuntimeError(c, "Missing required arg #%d", index);
-
-      return from_nasal<T>(args[index]);
-    }
-
-    template<class T>
-    naRef to_nasal(T arg) const
-    {
-      return nasal::to_nasal(c, arg);
-    }
-
-    template<class T>
-    typename from_nasal_ptr<T>::return_type
-    from_nasal(naRef ref) const
-    {
-      return (*from_nasal_ptr<T>::get())(c, ref);
-    }
-
-    naContext   c;
-    size_t      argc;
-    naRef      *args;
-  };
-
   /**
    * Class for exposing C++ objects to Nasal
    *
@@ -972,4 +871,20 @@ namespace nasal
 
 } // namespace nasal
 
+/**
+ * Convert every shared pointer to a ghost.
+ */
+// Needs to be outside any namespace to mark ADL work
+template<class T>
+typename boost::enable_if<
+  nasal::internal::has_element_type<
+    typename nasal::internal::reduced_type<T>::type
+  >,
+  naRef
+>::type
+to_nasal_helper(naContext c, T ptr)
+{
+  return nasal::Ghost<T>::create(c, ptr);
+}
+
 #endif /* SG_NASAL_GHOST_HXX_ */
diff --git a/simgear/nasal/cppbind/NasalCallContext.hxx b/simgear/nasal/cppbind/NasalCallContext.hxx
new file mode 100644 (file)
index 0000000..235f619
--- /dev/null
@@ -0,0 +1,135 @@
+///@file
+/// Call context for Nasal extension functions
+///
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// 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_CALL_CONTEXT_HXX_
+#define SG_NASAL_CALL_CONTEXT_HXX_
+
+#include "from_nasal.hxx"
+#include "to_nasal.hxx"
+
+namespace nasal
+{
+
+  /**
+   * Context passed to a function/method being called from Nasal
+   */
+  struct CallContext
+  {
+    CallContext(naContext c, size_t argc, naRef* args):
+      c(c),
+      argc(argc),
+      args(args)
+    {}
+
+    bool isNumeric(size_t index) const
+    {
+      return (index < argc && naIsNum(args[index]));
+    }
+
+    bool isString(size_t index) const
+    {
+      return (index < argc && naIsString(args[index]));
+    }
+
+    bool isHash(size_t index) const
+    {
+      return (index < argc && naIsHash(args[index]));
+    }
+
+    bool isVector(size_t index) const
+    {
+      return (index < argc && naIsVector(args[index]));
+    }
+
+    bool isGhost(size_t index) const
+    {
+      return (index < argc && naIsGhost(args[index]));
+    }
+
+    void popFront(size_t num = 1)
+    {
+      if( argc < num )
+        return;
+
+      args += num;
+      argc -= num;
+    }
+
+    void popBack(size_t num = 1)
+    {
+      if( argc < num )
+        return;
+
+      argc -= num;
+    }
+
+    /**
+     * Get the argument with given index if it exists. Otherwise returns the
+     * passed default value.
+     *
+     * @tparam T    Type of argument (converted using ::from_nasal)
+     * @param index Index of requested argument
+     * @param def   Default value returned if too few arguments available
+     */
+    template<class T>
+    typename from_nasal_ptr<T>::return_type
+    getArg(size_t index, const T& def = T()) const
+    {
+      if( index >= argc )
+        return def;
+
+      return from_nasal<T>(args[index]);
+    }
+
+    /**
+     * Get the argument with given index. Raises a Nasal runtime error if there
+     * are to few arguments available.
+     */
+    template<class T>
+    typename from_nasal_ptr<T>::return_type
+    requireArg(size_t index) const
+    {
+      if( index >= argc )
+        naRuntimeError(c, "Missing required arg #%d", index);
+
+      return from_nasal<T>(args[index]);
+    }
+
+    template<class T>
+    naRef to_nasal(T arg) const
+    {
+      return nasal::to_nasal(c, arg);
+    }
+
+    template<class T>
+    typename from_nasal_ptr<T>::return_type
+    from_nasal(naRef ref) const
+    {
+      return (*from_nasal_ptr<T>::get())(c, ref);
+    }
+
+    naContext   c;
+    size_t      argc;
+    naRef      *args;
+  };
+
+} // namespace nasal
+
+
+#endif /* SG_NASAL_CALL_CONTEXT_HXX_ */
index 23e5e33f4722c5cf7afeadb3b045f3b7cf35a96e..876f3c45e17d080e4ab8620c501ada66b8008d08 100644 (file)
@@ -64,16 +64,12 @@ typedef boost::shared_ptr<Derived> DerivedPtr;
 typedef boost::shared_ptr<DoubleDerived> DoubleDerivedPtr;
 typedef boost::shared_ptr<DoubleDerived2> DoubleDerived2Ptr;
 
-naRef to_nasal_helper(naContext c, const BasePtr& base)
-{
-  return nasal::Ghost<BasePtr>::create(c, base);
-}
-
 naRef derivedFreeMember(Derived&, const nasal::CallContext&) { return naNil(); }
 naRef f_derivedGetX(naContext c, const Derived& d)
 {
   return nasal::to_nasal(c, d.getX());
 }
+naRef f_freeFunction(nasal::CallContext) { return naNil(); }
 
 int main(int argc, char* argv[])
 {
@@ -124,6 +120,7 @@ int main(int argc, char* argv[])
   hash.set("vec2", vec);
   hash.set("name", "my-name");
   hash.set("string", std::string("blub"));
+  hash.set("func", &f_freeFunction);
 
   r = to_nasal(c, hash);
   VERIFY( naIsHash(r) );
@@ -165,6 +162,8 @@ int main(int argc, char* argv[])
     .bases< Ghost<DerivedPtr> >()
     .member("base", &DoubleDerived2::getBase);
 
+  nasal::to_nasal(c, DoubleDerived2Ptr());
+
   BasePtr d( new Derived );
   naRef derived = Ghost<BasePtr>::create(c, d);
   VERIFY( naIsGhost(derived) );
index bc1f25e2e8e29367c95794f720301a30d75365ad..fd744fde6fbe3125502c20aaebd1da074a4aeda2 100644 (file)
 
 #include "to_nasal_helper.hxx"
 #include <simgear/nasal/cppbind/NasalHash.hxx>
+#include <simgear/nasal/cppbind/Ghost.hxx>
 
 #include <simgear/misc/sg_path.hxx>
 
+#include <boost/function.hpp>
+
 namespace nasal
 {
   //----------------------------------------------------------------------------
@@ -37,12 +40,6 @@ namespace nasal
     return to_nasal_helper(c, std::string(str));
   }
 
-  //----------------------------------------------------------------------------
-  naRef to_nasal_helper(naContext c, naCFunction func)
-  {
-    return naNewFunc(c, naNewCCode(c, func));
-  }
-
   //----------------------------------------------------------------------------
   naRef to_nasal_helper(naContext c, const Hash& hash)
   {
@@ -60,4 +57,45 @@ namespace nasal
   {
     return to_nasal_helper(c, path.str());
   }
+
+  //----------------------------------------------------------------------------
+  naRef to_nasal_helper(naContext c, naCFunction func)
+  {
+    return naNewFunc(c, naNewCCode(c, func));
+  }
+
+  //----------------------------------------------------------------------------
+  static naRef free_function_invoker( naContext c,
+                                      naRef me,
+                                      int argc,
+                                      naRef* args,
+                                      void* user_data )
+  {
+    free_function_t* func = static_cast<free_function_t*>(user_data);
+    assert(func);
+    return (*func)(nasal::CallContext(c, argc, args));
+  }
+
+  //----------------------------------------------------------------------------
+  static void free_function_destroy(void* func)
+  {
+    delete static_cast<free_function_t*>(func);
+  }
+
+  //----------------------------------------------------------------------------
+  naRef to_nasal_helper(naContext c, const free_function_t& func)
+  {
+    return naNewFunc
+    (
+      c,
+      naNewCCodeUD
+      (
+        c,
+        &free_function_invoker,
+        new free_function_t(func),
+        &free_function_destroy
+      )
+    );
+  }
+
 } // namespace nasal
index 237366a9dec2a94cdd08497f6a6e5127a5eafd39..c74282ef3b02cbb1e181708eb1bed895d451c066 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <simgear/nasal/nasal.h>
 
+#include <boost/function/function_fwd.hpp>
 #include <boost/utility/enable_if.hpp>
 #include <boost/call_traits.hpp>
 #include <boost/type_traits.hpp>
@@ -36,8 +37,11 @@ class SGPath;
 
 namespace nasal
 {
+  class CallContext;
   class Hash;
 
+  typedef boost::function<naRef (CallContext)> free_function_t;
+
   /**
    * Convert std::string to Nasal string
    */
@@ -49,11 +53,6 @@ namespace nasal
   // 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
    */
@@ -66,6 +65,13 @@ namespace nasal
 
   naRef to_nasal_helper(naContext c, const SGPath& path);
 
+  /**
+   * Convert function pointer to Nasal function
+   */
+  naRef to_nasal_helper(naContext c, naCFunction func);
+
+  naRef to_nasal_helper(naContext c, const free_function_t& func);
+
   /**
    * Convert a numeric type to Nasal number
    */