cppbind: nasal::Context refactoring and doxygen improvements.
This commit is contained in:
@@ -770,7 +770,7 @@ namespace nasal
|
||||
|
||||
/**
|
||||
* Register anything that accepts an object instance and a
|
||||
* nasal::CallContext whith automatic conversion of the return type to
|
||||
* nasal::CallContext with automatic conversion of the return type to
|
||||
* Nasal.
|
||||
*
|
||||
* @code{cpp}
|
||||
@@ -1148,7 +1148,7 @@ namespace nasal
|
||||
const CallContext& ctx
|
||||
)
|
||||
{
|
||||
return (*to_nasal_ptr<Ret>::get())(ctx.c, func(obj, ctx));
|
||||
return (*to_nasal_ptr<Ret>::get())(ctx.c_ctx(), func(obj, ctx));
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
#ifndef SG_NASAL_CALL_CONTEXT_HXX_
|
||||
#define SG_NASAL_CALL_CONTEXT_HXX_
|
||||
|
||||
#include "from_nasal.hxx"
|
||||
#include "to_nasal.hxx"
|
||||
#include "NasalContext.hxx"
|
||||
|
||||
namespace nasal
|
||||
{
|
||||
@@ -29,11 +28,12 @@ namespace nasal
|
||||
/**
|
||||
* Context passed to a function/method being called from Nasal
|
||||
*/
|
||||
class CallContext
|
||||
class CallContext:
|
||||
public ContextWrapper
|
||||
{
|
||||
public:
|
||||
CallContext(naContext c, naRef me, size_t argc, naRef* args):
|
||||
c(c),
|
||||
ContextWrapper(c),
|
||||
me(me),
|
||||
argc(argc),
|
||||
args(args)
|
||||
@@ -102,28 +102,14 @@ namespace nasal
|
||||
requireArg(size_t index) const
|
||||
{
|
||||
if( index >= argc )
|
||||
naRuntimeError(c, "Missing required arg #%d", index);
|
||||
runtimeError("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;
|
||||
naRef me;
|
||||
size_t argc;
|
||||
naRef *args;
|
||||
naRef me;
|
||||
size_t argc;
|
||||
naRef *args;
|
||||
};
|
||||
|
||||
} // namespace nasal
|
||||
|
||||
@@ -17,13 +17,59 @@
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
#include "NasalContext.hxx"
|
||||
#include "NasalHash.hxx"
|
||||
#include "NasalString.hxx"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace nasal
|
||||
{
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ContextWrapper::ContextWrapper(naContext ctx):
|
||||
_ctx(ctx)
|
||||
{
|
||||
assert(_ctx);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ContextWrapper::operator naContext()
|
||||
{
|
||||
return _ctx;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
naContext ContextWrapper::c_ctx() const
|
||||
{
|
||||
return const_cast<naContext>(_ctx);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Hash ContextWrapper::newHash()
|
||||
{
|
||||
return Hash(_ctx);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
String ContextWrapper::newString(const char* str)
|
||||
{
|
||||
return String(_ctx, str);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
naRef ContextWrapper::newVector(std::initializer_list<naRef> vals)
|
||||
{
|
||||
naRef vec = naNewVector(_ctx);
|
||||
naVec_setsize(_ctx, vec, vals.size());
|
||||
int i = 0;
|
||||
for(naRef val: vals)
|
||||
naVec_set(vec, i++, val);
|
||||
return vec;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Context::Context():
|
||||
_ctx(naNewContext())
|
||||
ContextWrapper(naNewContext())
|
||||
{
|
||||
|
||||
}
|
||||
@@ -32,18 +78,7 @@ namespace nasal
|
||||
Context::~Context()
|
||||
{
|
||||
naFreeContext(_ctx);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Context::operator naContext()
|
||||
{
|
||||
return _ctx;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Hash Context::newHash()
|
||||
{
|
||||
return Hash(_ctx);
|
||||
_ctx = nullptr;
|
||||
}
|
||||
|
||||
} // namespace nasal
|
||||
|
||||
@@ -19,26 +19,83 @@
|
||||
#ifndef SG_NASAL_CONTEXT_HXX_
|
||||
#define SG_NASAL_CONTEXT_HXX_
|
||||
|
||||
#include "NasalHash.hxx"
|
||||
#include "from_nasal.hxx"
|
||||
#include "to_nasal.hxx"
|
||||
|
||||
namespace nasal
|
||||
{
|
||||
class Hash;
|
||||
class String;
|
||||
|
||||
/**
|
||||
* Manage lifetime and encapsulate a Nasal context.
|
||||
* Wraps a nasal ::naContext without taking ownership/managing its lifetime
|
||||
*/
|
||||
class Context
|
||||
class ContextWrapper
|
||||
{
|
||||
public:
|
||||
explicit ContextWrapper(naContext ctx);
|
||||
|
||||
operator naContext();
|
||||
|
||||
/** Convert to non-const ::naContext for usage with C-APIs */
|
||||
naContext c_ctx() const;
|
||||
|
||||
Hash newHash();
|
||||
String newString(const char* str);
|
||||
|
||||
/** Create a new nasal vector and fill it with the given values */
|
||||
template<class ... Vals>
|
||||
naRef newVector(Vals ... vals)
|
||||
{
|
||||
return newVector({to_nasal(vals)...});
|
||||
}
|
||||
|
||||
/** Raise a nasal runtime error */
|
||||
template<class ... Args>
|
||||
void runtimeError(const char* fmt, Args ... args) const
|
||||
{
|
||||
naRuntimeError(c_ctx(), fmt, args...);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
naRef to_nasal(T arg) const
|
||||
{
|
||||
return nasal::to_nasal(_ctx, arg);
|
||||
}
|
||||
|
||||
template<class T, size_t N>
|
||||
naRef to_nasal(const T(&array)[N]) const
|
||||
{
|
||||
return nasal::to_nasal(_ctx, array);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename from_nasal_ptr<T>::return_type
|
||||
from_nasal(naRef ref) const
|
||||
{
|
||||
return (*from_nasal_ptr<T>::get())(_ctx, ref);
|
||||
}
|
||||
|
||||
protected:
|
||||
naContext _ctx;
|
||||
|
||||
// Not exposed to avoid confusion of intializer_list<naRef> to variadic
|
||||
// arguments
|
||||
naRef newVector(std::initializer_list<naRef> vals);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates and manages the lifetime of a ::naContext
|
||||
*/
|
||||
class Context:
|
||||
public ContextWrapper
|
||||
{
|
||||
public:
|
||||
Context();
|
||||
~Context();
|
||||
|
||||
operator naContext();
|
||||
|
||||
Hash newHash();
|
||||
|
||||
protected:
|
||||
naContext _ctx;
|
||||
Context(const Context&) = delete;
|
||||
Context& operator=(const Context&) = delete;
|
||||
};
|
||||
|
||||
} // namespace nasal
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace nasal
|
||||
*
|
||||
* @param str Existing Nasal String
|
||||
*/
|
||||
String(naRef str);
|
||||
explicit String(naRef str);
|
||||
|
||||
const char* c_str() const;
|
||||
const char* begin() const;
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace nasal
|
||||
{
|
||||
naRef _ref;
|
||||
|
||||
Me(naRef ref):
|
||||
Me(naRef ref = naNil()):
|
||||
_ref(ref)
|
||||
{}
|
||||
|
||||
|
||||
@@ -20,50 +20,29 @@
|
||||
#ifndef SG_NASAL_TESTCONTEXT_HXX_
|
||||
#define SG_NASAL_TESTCONTEXT_HXX_
|
||||
|
||||
#include <simgear/nasal/cppbind/NasalCallContext.hxx>
|
||||
#include <simgear/nasal/cppbind/NasalContext.hxx>
|
||||
|
||||
class TestContext:
|
||||
public nasal::CallContext
|
||||
public nasal::Context
|
||||
{
|
||||
public:
|
||||
TestContext():
|
||||
CallContext(naNewContext(), naNil(), 0, 0)
|
||||
{}
|
||||
|
||||
~TestContext()
|
||||
{
|
||||
naFreeContext(c);
|
||||
}
|
||||
|
||||
void runGC()
|
||||
{
|
||||
naFreeContext(c);
|
||||
naFreeContext(_ctx);
|
||||
naGC();
|
||||
c = naNewContext();
|
||||
_ctx = naNewContext();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T from_str(const std::string& str)
|
||||
template<class T = naRef>
|
||||
T exec(const std::string& code, nasal::Me me)
|
||||
{
|
||||
return from_nasal<T>(to_nasal(str));
|
||||
return from_nasal<T>(execImpl(code, me));
|
||||
}
|
||||
|
||||
naRef exec(const std::string& code_str, nasal::Me me)
|
||||
{
|
||||
int err_line = -1;
|
||||
naRef code = naParseCode( c, to_nasal("<TextContext::exec>"), 0,
|
||||
(char*)code_str.c_str(), code_str.length(),
|
||||
&err_line );
|
||||
if( !naIsCode(code) )
|
||||
throw std::runtime_error("Failed to parse code: " + code_str);
|
||||
|
||||
return naCallMethod(code, me, 0, 0, naNil());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<class T = naRef>
|
||||
T exec(const std::string& code)
|
||||
{
|
||||
return from_nasal<T>(exec(code, naNil()));
|
||||
return from_nasal<T>(execImpl(code, {}));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -71,6 +50,26 @@ class TestContext:
|
||||
{
|
||||
return from_nasal<T>(to_nasal(str));
|
||||
}
|
||||
|
||||
protected:
|
||||
naRef execImpl(const std::string& code_str, nasal::Me me)
|
||||
{
|
||||
int err_line = -1;
|
||||
naRef code = naParseCode( _ctx, to_nasal("<TextContext::exec>"), 0,
|
||||
(char*)code_str.c_str(), code_str.length(),
|
||||
&err_line );
|
||||
if( !naIsCode(code) )
|
||||
throw std::runtime_error("Failed to parse code: " + code_str);
|
||||
|
||||
naRef ret = naCallMethod(code, me, 0, 0, naNil());
|
||||
|
||||
if( char* err = naGetError(_ctx) )
|
||||
throw std::runtime_error(
|
||||
"Failed to executed code: " + std::string(err)
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* SG_NASAL_TESTCONTEXT_HXX_ */
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#define BOOST_TEST_MODULE cppbind
|
||||
#include <BoostTestTargetConfig.h>
|
||||
|
||||
#include "TestContext.hxx"
|
||||
|
||||
#include <simgear/nasal/cppbind/Ghost.hxx>
|
||||
#include <simgear/nasal/cppbind/NasalHash.hxx>
|
||||
#include <simgear/nasal/cppbind/NasalString.hxx>
|
||||
@@ -117,42 +119,42 @@ naRef f_freeFunction(nasal::CallContext c) { return c.requireArg<naRef>(0); }
|
||||
|
||||
BOOST_AUTO_TEST_CASE( cppbind_misc_testing )
|
||||
{
|
||||
naContext c = naNewContext();
|
||||
TestContext c;
|
||||
naRef r;
|
||||
|
||||
using namespace nasal;
|
||||
|
||||
r = to_nasal(c, ENUM_ANOTHER);
|
||||
BOOST_CHECK_EQUAL(from_nasal<int>(c, r), ENUM_ANOTHER);
|
||||
r = c.to_nasal(ENUM_ANOTHER);
|
||||
BOOST_CHECK_EQUAL(c.from_nasal<int>(r), ENUM_ANOTHER);
|
||||
|
||||
r = to_nasal(c, "Test");
|
||||
r = c.to_nasal("Test");
|
||||
BOOST_CHECK( strncmp("Test", naStr_data(r), naStr_len(r)) == 0 );
|
||||
BOOST_CHECK_EQUAL(from_nasal<std::string>(c, r), "Test");
|
||||
BOOST_CHECK_EQUAL(c.from_nasal<std::string>(r), "Test");
|
||||
|
||||
r = to_nasal(c, std::string("Test"));
|
||||
r = c.to_nasal(std::string("Test"));
|
||||
BOOST_CHECK( strncmp("Test", naStr_data(r), naStr_len(r)) == 0 );
|
||||
BOOST_CHECK_EQUAL(from_nasal<std::string>(c, r), "Test");
|
||||
BOOST_CHECK_EQUAL(c.from_nasal<std::string>(r), "Test");
|
||||
|
||||
r = to_nasal(c, 42);
|
||||
r = c.to_nasal(42);
|
||||
BOOST_CHECK_EQUAL(naNumValue(r).num, 42);
|
||||
BOOST_CHECK_EQUAL(from_nasal<int>(c, r), 42);
|
||||
BOOST_CHECK_EQUAL(c.from_nasal<int>(r), 42);
|
||||
|
||||
r = to_nasal(c, 4.2f);
|
||||
r = c.to_nasal(4.2f);
|
||||
BOOST_CHECK_EQUAL(naNumValue(r).num, 4.2f);
|
||||
BOOST_CHECK_EQUAL(from_nasal<float>(c, r), 4.2f);
|
||||
BOOST_CHECK_EQUAL(c.from_nasal<float>(r), 4.2f);
|
||||
|
||||
float test_data[3] = {0, 4, 2};
|
||||
r = to_nasal(c, test_data);
|
||||
r = c.to_nasal(test_data);
|
||||
|
||||
SGVec2f vec(0,2);
|
||||
r = to_nasal(c, vec);
|
||||
BOOST_CHECK_EQUAL(from_nasal<SGVec2f>(c, r), vec);
|
||||
r = c.to_nasal(vec);
|
||||
BOOST_CHECK_EQUAL(c.from_nasal<SGVec2f>(r), vec);
|
||||
|
||||
std::vector<int> std_vec;
|
||||
r = to_nasal(c, std_vec);
|
||||
r = c.to_nasal(std_vec);
|
||||
|
||||
r = to_nasal(c, "string");
|
||||
BOOST_CHECK_THROW(from_nasal<int>(c, r), bad_nasal_cast);
|
||||
r = c.to_nasal("string");
|
||||
BOOST_CHECK_THROW(c.from_nasal<int>(r), bad_nasal_cast);
|
||||
|
||||
Hash hash(c);
|
||||
hash.set("vec", r);
|
||||
@@ -171,10 +173,10 @@ BOOST_AUTO_TEST_CASE( cppbind_misc_testing )
|
||||
it1 = it2;
|
||||
it3 = it2;
|
||||
|
||||
r = to_nasal(c, hash);
|
||||
r = c.to_nasal(hash);
|
||||
BOOST_REQUIRE( naIsHash(r) );
|
||||
|
||||
simgear::StringMap string_map = from_nasal<simgear::StringMap>(c, r);
|
||||
simgear::StringMap string_map = c.from_nasal<simgear::StringMap>(r);
|
||||
BOOST_CHECK_EQUAL(string_map.at("vec"), "string");
|
||||
BOOST_CHECK_EQUAL(string_map.at("name"), "my-name");
|
||||
BOOST_CHECK_EQUAL(string_map.at("string"), "blub");
|
||||
@@ -260,81 +262,81 @@ BOOST_AUTO_TEST_CASE( cppbind_misc_testing )
|
||||
Ghost<SGWeakRefBasedPtr>::init("SGWeakRefBasedPtr");
|
||||
|
||||
SGWeakRefBasedPtr weak_ptr(new SGWeakReferenceBasedClass());
|
||||
naRef nasal_ref = to_nasal(c, weak_ptr),
|
||||
nasal_ptr = to_nasal(c, weak_ptr.get());
|
||||
naRef nasal_ref = c.to_nasal(weak_ptr),
|
||||
nasal_ptr = c.to_nasal(weak_ptr.get());
|
||||
|
||||
BOOST_REQUIRE( naIsGhost(nasal_ref) );
|
||||
BOOST_REQUIRE( naIsGhost(nasal_ptr) );
|
||||
|
||||
SGWeakRefBasedPtr ptr1 = from_nasal<SGWeakRefBasedPtr>(c, nasal_ref),
|
||||
ptr2 = from_nasal<SGWeakRefBasedPtr>(c, nasal_ptr);
|
||||
SGWeakRefBasedPtr ptr1 = c.from_nasal<SGWeakRefBasedPtr>(nasal_ref),
|
||||
ptr2 = c.from_nasal<SGWeakRefBasedPtr>(nasal_ptr);
|
||||
|
||||
BOOST_CHECK_EQUAL(weak_ptr, ptr1);
|
||||
BOOST_CHECK_EQUAL(weak_ptr, ptr2);
|
||||
|
||||
|
||||
BOOST_REQUIRE( Ghost<BasePtr>::isInit() );
|
||||
nasal::to_nasal(c, DoubleDerived2Ptr());
|
||||
c.to_nasal(DoubleDerived2Ptr());
|
||||
|
||||
BasePtr d( new Derived );
|
||||
naRef derived = to_nasal(c, d);
|
||||
naRef derived = c.to_nasal(d);
|
||||
BOOST_REQUIRE( naIsGhost(derived) );
|
||||
BOOST_CHECK_EQUAL( std::string("DerivedPtr"), naGhost_type(derived)->name );
|
||||
|
||||
// Get member function from ghost...
|
||||
naRef thisGetter = naNil();
|
||||
BOOST_CHECK( naMember_get(c, derived, to_nasal(c, "this"), &thisGetter) );
|
||||
BOOST_CHECK( naMember_get(c, derived, c.to_nasal("this"), &thisGetter) );
|
||||
BOOST_CHECK( naIsFunc(thisGetter) );
|
||||
|
||||
// ...and check if it really gets passed the correct instance
|
||||
typedef boost::function<unsigned long (Me)> MemFunc;
|
||||
MemFunc fGetThis = from_nasal<MemFunc>(c, thisGetter);
|
||||
MemFunc fGetThis = c.from_nasal<MemFunc>(thisGetter);
|
||||
BOOST_REQUIRE( fGetThis );
|
||||
BOOST_CHECK_EQUAL( fGetThis(derived), (unsigned long)d.get() );
|
||||
|
||||
BasePtr d2( new DoubleDerived );
|
||||
derived = to_nasal(c, d2);
|
||||
derived = c.to_nasal(d2);
|
||||
BOOST_CHECK( naIsGhost(derived) );
|
||||
BOOST_CHECK_EQUAL( std::string("DoubleDerivedPtr"),
|
||||
naGhost_type(derived)->name );
|
||||
|
||||
BasePtr d3( new DoubleDerived2 );
|
||||
derived = to_nasal(c, d3);
|
||||
derived = c.to_nasal(d3);
|
||||
BOOST_CHECK( naIsGhost(derived) );
|
||||
BOOST_CHECK_EQUAL( std::string("DoubleDerived2Ptr"),
|
||||
naGhost_type(derived)->name );
|
||||
|
||||
SGRefBasedPtr ref_based( new SGReferenceBasedClass );
|
||||
naRef na_ref_based = to_nasal(c, ref_based.get());
|
||||
naRef na_ref_based = c.to_nasal(ref_based.get());
|
||||
BOOST_CHECK( naIsGhost(na_ref_based) );
|
||||
BOOST_CHECK_EQUAL( from_nasal<SGReferenceBasedClass*>(c, na_ref_based),
|
||||
BOOST_CHECK_EQUAL( c.from_nasal<SGReferenceBasedClass*>(na_ref_based),
|
||||
ref_based.get() );
|
||||
BOOST_CHECK_EQUAL( from_nasal<SGRefBasedPtr>(c, na_ref_based), ref_based );
|
||||
BOOST_CHECK_EQUAL( c.from_nasal<SGRefBasedPtr>(na_ref_based), ref_based );
|
||||
|
||||
BOOST_CHECK_EQUAL( from_nasal<BasePtr>(c, derived), d3 );
|
||||
BOOST_CHECK_NE( from_nasal<BasePtr>(c, derived), d2 );
|
||||
BOOST_CHECK_EQUAL( from_nasal<DerivedPtr>(c, derived),
|
||||
BOOST_CHECK_EQUAL( c.from_nasal<BasePtr>(derived), d3 );
|
||||
BOOST_CHECK_NE( c.from_nasal<BasePtr>(derived), d2 );
|
||||
BOOST_CHECK_EQUAL( c.from_nasal<DerivedPtr>(derived),
|
||||
boost::dynamic_pointer_cast<Derived>(d3) );
|
||||
BOOST_CHECK_EQUAL( from_nasal<DoubleDerived2Ptr>(c, derived),
|
||||
BOOST_CHECK_EQUAL( c.from_nasal<DoubleDerived2Ptr>(derived),
|
||||
boost::dynamic_pointer_cast<DoubleDerived2>(d3) );
|
||||
BOOST_CHECK_THROW( from_nasal<DoubleDerivedPtr>(c, derived), bad_nasal_cast );
|
||||
BOOST_CHECK_THROW( c.from_nasal<DoubleDerivedPtr>(derived), bad_nasal_cast );
|
||||
|
||||
std::map<std::string, BasePtr> instances;
|
||||
BOOST_CHECK( naIsHash(to_nasal(c, instances)) );
|
||||
BOOST_CHECK( naIsHash(c.to_nasal(instances)) );
|
||||
|
||||
std::map<std::string, DerivedPtr> instances_d;
|
||||
BOOST_CHECK( naIsHash(to_nasal(c, instances_d)) );
|
||||
BOOST_CHECK( naIsHash(c.to_nasal(instances_d)) );
|
||||
|
||||
std::map<std::string, int> int_map;
|
||||
BOOST_CHECK( naIsHash(to_nasal(c, int_map)) );
|
||||
BOOST_CHECK( naIsHash(c.to_nasal(int_map)) );
|
||||
|
||||
std::map<std::string, std::vector<int> > int_vector_map;
|
||||
BOOST_CHECK( naIsHash(to_nasal(c, int_vector_map)) );
|
||||
BOOST_CHECK( naIsHash(c.to_nasal(int_vector_map)) );
|
||||
|
||||
simgear::StringMap dict =
|
||||
simgear::StringMap("hello", "value")
|
||||
("key2", "value2");
|
||||
naRef na_dict = to_nasal(c, dict);
|
||||
naRef na_dict = c.to_nasal(dict);
|
||||
BOOST_REQUIRE( naIsHash(na_dict) );
|
||||
BOOST_CHECK_EQUAL( Hash(na_dict, c).get<std::string>("key2"), "value2" );
|
||||
|
||||
@@ -346,65 +348,44 @@ BOOST_AUTO_TEST_CASE( cppbind_misc_testing )
|
||||
|
||||
Hash obj(c);
|
||||
obj.set("parents", parents);
|
||||
BOOST_CHECK_EQUAL( from_nasal<BasePtr>(c, obj.get_naRef()), d3 );
|
||||
BOOST_CHECK_EQUAL( c.from_nasal<BasePtr>(obj.get_naRef()), d3 );
|
||||
|
||||
// Check recursive parents (aka parent-of-parent)
|
||||
std::vector<naRef> parents2;
|
||||
parents2.push_back(obj.get_naRef());
|
||||
Hash derived_obj(c);
|
||||
derived_obj.set("parents", parents2);
|
||||
BOOST_CHECK_EQUAL( from_nasal<BasePtr>(c, derived_obj.get_naRef()), d3 );
|
||||
BOOST_CHECK_EQUAL( c.from_nasal<BasePtr>(derived_obj.get_naRef()), d3 );
|
||||
|
||||
std::vector<naRef> nasal_objects;
|
||||
nasal_objects.push_back( Ghost<BasePtr>::makeGhost(c, d) );
|
||||
nasal_objects.push_back( Ghost<BasePtr>::makeGhost(c, d2) );
|
||||
nasal_objects.push_back( Ghost<BasePtr>::makeGhost(c, d3) );
|
||||
naRef obj_vec = to_nasal(c, nasal_objects);
|
||||
naRef obj_vec = c.to_nasal(nasal_objects);
|
||||
|
||||
std::vector<BasePtr> objects = from_nasal<std::vector<BasePtr> >(c, obj_vec);
|
||||
std::vector<BasePtr> objects = c.from_nasal<std::vector<BasePtr> >(obj_vec);
|
||||
BOOST_CHECK_EQUAL( objects[0], d );
|
||||
BOOST_CHECK_EQUAL( objects[1], d2 );
|
||||
BOOST_CHECK_EQUAL( objects[2], d3 );
|
||||
|
||||
{
|
||||
// Calling fallback setter for unset values
|
||||
const char* src_code = "me.test = 3;";
|
||||
int errLine = -1;
|
||||
naRef code = naParseCode( c, to_nasal(c, "source.nas"), 0,
|
||||
(char*)src_code, strlen(src_code),
|
||||
&errLine );
|
||||
ret = naCallMethod(code, derived, 0, 0, naNil());
|
||||
// Calling fallback setter for unset values
|
||||
BOOST_CHECK_EQUAL( c.exec<int>("me.test = 3;", derived), 3 );
|
||||
|
||||
BOOST_REQUIRE( !naGetError(c) ); // TODO real error check (this seems to
|
||||
// always return 0...
|
||||
BOOST_CHECK_EQUAL( from_nasal<int>(c, ret), 3 );
|
||||
}
|
||||
{
|
||||
// Calling generic (fallback) getter
|
||||
const char* src_code = "var a = me.get_test;";
|
||||
int errLine = -1;
|
||||
naRef code = naParseCode( c, to_nasal(c, "source.nas"), 0,
|
||||
(char*)src_code, strlen(src_code),
|
||||
&errLine );
|
||||
ret = naCallMethod(code, derived, 0, 0, naNil());
|
||||
|
||||
BOOST_REQUIRE( !naGetError(c) ); // TODO real error check (this seems to
|
||||
// always return 0...
|
||||
BOOST_CHECK_EQUAL( from_nasal<std::string>(c, ret), "generic-get" );
|
||||
}
|
||||
// Calling generic (fallback) getter
|
||||
BOOST_CHECK_EQUAL( c.exec<std::string>("var a = me.get_test;", derived),
|
||||
"generic-get" );
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Test nasal::CallContext
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
int int_vec[] = {1,2,3};
|
||||
std::map<std::string, std::string> map;
|
||||
naRef args[] = {
|
||||
to_nasal(c, std::string("test-arg")),
|
||||
to_nasal(c, 4),
|
||||
to_nasal(c, int_vec),
|
||||
to_nasal(c, map)
|
||||
c.to_nasal(std::string("test-arg")),
|
||||
c.to_nasal(4),
|
||||
c.to_nasal(int_vec),
|
||||
c.to_nasal(map)
|
||||
};
|
||||
CallContext cc(c, naNil(), sizeof(args)/sizeof(args[0]), args);
|
||||
BOOST_CHECK_EQUAL( cc.requireArg<std::string>(0), "test-arg" );
|
||||
@@ -419,15 +400,15 @@ BOOST_AUTO_TEST_CASE( cppbind_misc_testing )
|
||||
BOOST_CHECK( cc.isVector(2) );
|
||||
BOOST_CHECK( cc.isHash(3) );
|
||||
|
||||
naRef args_vec = nasal::to_nasal(c, args);
|
||||
naRef args_vec = c.to_nasal(args);
|
||||
BOOST_CHECK( naIsVector(args_vec) );
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Test nasal::String
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
String string( to_nasal(c, "Test") );
|
||||
BOOST_CHECK_EQUAL( from_nasal<std::string>(c, string.get_naRef()), "Test" );
|
||||
String string( c.to_nasal("Test") );
|
||||
BOOST_CHECK_EQUAL( c.from_nasal<std::string>(string.get_naRef()), "Test" );
|
||||
BOOST_CHECK_EQUAL( string.c_str(), std::string("Test") );
|
||||
BOOST_CHECK( string.starts_with(string) );
|
||||
BOOST_CHECK( string.starts_with(String(c, "T")) );
|
||||
@@ -453,6 +434,16 @@ BOOST_AUTO_TEST_CASE( cppbind_misc_testing )
|
||||
BOOST_CHECK_EQUAL( string.find_first_not_of(String(c, "Tse"), 2), 3 );
|
||||
BOOST_CHECK_EQUAL( string.find_first_not_of(String(c, "abc")), 0 );
|
||||
BOOST_CHECK_EQUAL( string.find_first_not_of(String(c, "abc"), 20), String::npos );
|
||||
|
||||
naFreeContext(c);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( cppbind_context )
|
||||
{
|
||||
nasal::Context ctx;
|
||||
naRef vec = ctx.newVector(1, 2, 3.4, "test");
|
||||
BOOST_REQUIRE( naIsVector(vec) );
|
||||
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(vec, 0)), 1);
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(vec, 1)), 2);
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<double>(naVec_get(vec, 2)), 3.4);
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<std::string>(naVec_get(vec, 3)), "test");
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ static naGhostType ghost_type = {
|
||||
static naRef createTestGhost(TestContext& c, intptr_t p)
|
||||
{
|
||||
active_instances.insert(p);
|
||||
return naNewGhost(c.c, &ghost_type, (void*)p);
|
||||
return naNewGhost(c, &ghost_type, (void*)p);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
///@file
|
||||
/// The Nasal scripting language
|
||||
///
|
||||
#ifndef _NASAL_H
|
||||
#define _NASAL_H
|
||||
#ifdef __cplusplus
|
||||
@@ -15,12 +18,14 @@ extern "C" {
|
||||
#define GCC_PURE
|
||||
#endif
|
||||
|
||||
/** Nasal context pointer */
|
||||
typedef struct Context* naContext;
|
||||
|
||||
// The function signature for an extension function:
|
||||
/** Function signature for an extension function */
|
||||
typedef naRef (*naCFunction)(naContext ctx, naRef me, int argc, naRef* args);
|
||||
|
||||
// The function signature for an extension function with userdata passed back:
|
||||
/** Function signature for an extension function with @p user_data passed back
|
||||
*/
|
||||
typedef naRef (*naCFunctionU)
|
||||
(naContext ctx, naRef me, int argc, naRef* args, void* user_data);
|
||||
|
||||
@@ -258,7 +263,7 @@ void naHash_set(naRef hash, naRef key, naRef val);
|
||||
void naHash_cset(naRef hash, char* key, naRef val);
|
||||
void naHash_delete(naRef hash, naRef key);
|
||||
/**
|
||||
* Store the keys in ::hash into the vector at ::dst
|
||||
* Store the keys in @p hash into the vector at @p dst
|
||||
*
|
||||
* @see ::naNewVector
|
||||
*/
|
||||
@@ -273,25 +278,25 @@ typedef struct naGhostType {
|
||||
} naGhostType;
|
||||
|
||||
/**
|
||||
* Create a ghost for an object without any attributes. If ::t contains pointers
|
||||
* to get_member or set_member function they will be ignored.
|
||||
* Create a ghost for an object without any attributes. If @p t contains
|
||||
* pointers to get_member or set_member function they will be ignored.
|
||||
*/
|
||||
naRef naNewGhost(naContext c, naGhostType* t, void* ghost);
|
||||
/**
|
||||
* Create a ghost for an object. This version uses the get_member and set_member
|
||||
* function pointers in ::t upon trying to get or set a member respectively from
|
||||
* Nasal.
|
||||
* function pointers in @p t upon trying to get or set a member respectively
|
||||
* from Nasal.
|
||||
*/
|
||||
naRef naNewGhost2(naContext c, naGhostType* t, void* ghost);
|
||||
naGhostType* naGhost_type(naRef ghost);
|
||||
void* naGhost_ptr(naRef ghost);
|
||||
/**
|
||||
* Attach a nasal object to the given ghost. Binds the lifetime of @a data to
|
||||
* the lifetime of the @a ghost.
|
||||
* Attach a nasal object to the given ghost. Binds the lifetime of @p data to
|
||||
* the lifetime of the @p ghost.
|
||||
*/
|
||||
void naGhost_setData(naRef ghost, naRef data);
|
||||
/**
|
||||
* Retrieve the object attached to the @a ghost, previously set with
|
||||
* Retrieve the object attached to the @p ghost, previously set with
|
||||
* naGhost_setData().
|
||||
*/
|
||||
naRef naGhost_data(naRef ghost);
|
||||
|
||||
Reference in New Issue
Block a user