cppbind: allow adding free functions accepting nasal::CallContext and do some cleanup
This commit is contained in:
@@ -2,6 +2,7 @@ include (SimGearComponent)
|
||||
|
||||
set(HEADERS
|
||||
Ghost.hxx
|
||||
NasalCallContext.hxx
|
||||
NasalHash.hxx
|
||||
NasalString.hxx
|
||||
from_nasal.hxx
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
135
simgear/nasal/cppbind/NasalCallContext.hxx
Normal file
135
simgear/nasal/cppbind/NasalCallContext.hxx
Normal 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_ */
|
||||
@@ -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) );
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user