set(HEADERS
Ghost.hxx
+ NasalCallContext.hxx
NasalHash.hxx
NasalString.hxx
from_nasal.hxx
#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>
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
*
} // 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_ */
--- /dev/null
+///@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_ */
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[])
{
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) );
.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) );
#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
{
//----------------------------------------------------------------------------
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)
{
{
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
#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>
namespace nasal
{
+ class CallContext;
class Hash;
+ typedef boost::function<naRef (CallContext)> free_function_t;
+
/**
* Convert std::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 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
*/