cppbind: allow adding free functions accepting nasal::CallContext and do some cleanup

This commit is contained in:
Thomas Geymayer
2013-03-06 17:00:38 +01:00
parent ff844f6760
commit 8e0c15e32e
6 changed files with 221 additions and 127 deletions

View File

@@ -2,6 +2,7 @@ include (SimGearComponent)
set(HEADERS
Ghost.hxx
NasalCallContext.hxx
NasalHash.hxx
NasalString.hxx
from_nasal.hxx

View 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_ */

View File

@@ -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_ */

View 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) );

View File

@@ -18,9 +18,12 @@
#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

View 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
*/