cppbind: nasal::Context refactoring and doxygen improvements.

This commit is contained in:
Thomas Geymayer
2018-01-09 22:50:29 +01:00
parent 455753c774
commit 99ee3d9dec
10 changed files with 242 additions and 169 deletions
+2 -2
View File
@@ -770,7 +770,7 @@ namespace nasal
/** /**
* Register anything that accepts an object instance and a * 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. * Nasal.
* *
* @code{cpp} * @code{cpp}
@@ -1148,7 +1148,7 @@ namespace nasal
const CallContext& ctx 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));
}; };
/** /**
+8 -22
View File
@@ -20,8 +20,7 @@
#ifndef SG_NASAL_CALL_CONTEXT_HXX_ #ifndef SG_NASAL_CALL_CONTEXT_HXX_
#define SG_NASAL_CALL_CONTEXT_HXX_ #define SG_NASAL_CALL_CONTEXT_HXX_
#include "from_nasal.hxx" #include "NasalContext.hxx"
#include "to_nasal.hxx"
namespace nasal namespace nasal
{ {
@@ -29,11 +28,12 @@ namespace nasal
/** /**
* Context passed to a function/method being called from Nasal * Context passed to a function/method being called from Nasal
*/ */
class CallContext class CallContext:
public ContextWrapper
{ {
public: public:
CallContext(naContext c, naRef me, size_t argc, naRef* args): CallContext(naContext c, naRef me, size_t argc, naRef* args):
c(c), ContextWrapper(c),
me(me), me(me),
argc(argc), argc(argc),
args(args) args(args)
@@ -102,28 +102,14 @@ namespace nasal
requireArg(size_t index) const requireArg(size_t index) const
{ {
if( index >= argc ) if( index >= argc )
naRuntimeError(c, "Missing required arg #%d", index); runtimeError("Missing required arg #%d", index);
return from_nasal<T>(args[index]); return from_nasal<T>(args[index]);
} }
template<class T> naRef me;
naRef to_nasal(T arg) const size_t argc;
{ naRef *args;
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;
}; };
} // namespace nasal } // namespace nasal
+48 -13
View File
@@ -17,13 +17,59 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include "NasalContext.hxx" #include "NasalContext.hxx"
#include "NasalHash.hxx"
#include "NasalString.hxx"
#include <cassert>
namespace nasal 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(): Context::Context():
_ctx(naNewContext()) ContextWrapper(naNewContext())
{ {
} }
@@ -32,18 +78,7 @@ namespace nasal
Context::~Context() Context::~Context()
{ {
naFreeContext(_ctx); naFreeContext(_ctx);
} _ctx = nullptr;
//----------------------------------------------------------------------------
Context::operator naContext()
{
return _ctx;
}
//----------------------------------------------------------------------------
Hash Context::newHash()
{
return Hash(_ctx);
} }
} // namespace nasal } // namespace nasal
+66 -9
View File
@@ -19,26 +19,83 @@
#ifndef SG_NASAL_CONTEXT_HXX_ #ifndef SG_NASAL_CONTEXT_HXX_
#define SG_NASAL_CONTEXT_HXX_ #define SG_NASAL_CONTEXT_HXX_
#include "NasalHash.hxx" #include "from_nasal.hxx"
#include "to_nasal.hxx"
namespace nasal 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: public:
Context(); Context();
~Context(); ~Context();
operator naContext(); Context(const Context&) = delete;
Context& operator=(const Context&) = delete;
Hash newHash();
protected:
naContext _ctx;
}; };
} // namespace nasal } // namespace nasal
+1 -1
View File
@@ -47,7 +47,7 @@ namespace nasal
* *
* @param str Existing Nasal String * @param str Existing Nasal String
*/ */
String(naRef str); explicit String(naRef str);
const char* c_str() const; const char* c_str() const;
const char* begin() const; const char* begin() const;
@@ -84,7 +84,7 @@ namespace nasal
{ {
naRef _ref; naRef _ref;
Me(naRef ref): Me(naRef ref = naNil()):
_ref(ref) _ref(ref)
{} {}
+29 -30
View File
@@ -20,50 +20,29 @@
#ifndef SG_NASAL_TESTCONTEXT_HXX_ #ifndef SG_NASAL_TESTCONTEXT_HXX_
#define SG_NASAL_TESTCONTEXT_HXX_ #define SG_NASAL_TESTCONTEXT_HXX_
#include <simgear/nasal/cppbind/NasalCallContext.hxx> #include <simgear/nasal/cppbind/NasalContext.hxx>
class TestContext: class TestContext:
public nasal::CallContext public nasal::Context
{ {
public: public:
TestContext():
CallContext(naNewContext(), naNil(), 0, 0)
{}
~TestContext()
{
naFreeContext(c);
}
void runGC() void runGC()
{ {
naFreeContext(c); naFreeContext(_ctx);
naGC(); naGC();
c = naNewContext(); _ctx = naNewContext();
} }
template<class T> template<class T = naRef>
T from_str(const std::string& str) 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) template<class T = naRef>
{
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>
T exec(const std::string& code) T exec(const std::string& code)
{ {
return from_nasal<T>(exec(code, naNil())); return from_nasal<T>(execImpl(code, {}));
} }
template<class T> template<class T>
@@ -71,6 +50,26 @@ class TestContext:
{ {
return from_nasal<T>(to_nasal(str)); 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_ */ #endif /* SG_NASAL_TESTCONTEXT_HXX_ */
+71 -80
View File
@@ -1,6 +1,8 @@
#define BOOST_TEST_MODULE cppbind #define BOOST_TEST_MODULE cppbind
#include <BoostTestTargetConfig.h> #include <BoostTestTargetConfig.h>
#include "TestContext.hxx"
#include <simgear/nasal/cppbind/Ghost.hxx> #include <simgear/nasal/cppbind/Ghost.hxx>
#include <simgear/nasal/cppbind/NasalHash.hxx> #include <simgear/nasal/cppbind/NasalHash.hxx>
#include <simgear/nasal/cppbind/NasalString.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 ) BOOST_AUTO_TEST_CASE( cppbind_misc_testing )
{ {
naContext c = naNewContext(); TestContext c;
naRef r; naRef r;
using namespace nasal; using namespace nasal;
r = to_nasal(c, ENUM_ANOTHER); r = c.to_nasal(ENUM_ANOTHER);
BOOST_CHECK_EQUAL(from_nasal<int>(c, r), 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( 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( 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(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(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}; float test_data[3] = {0, 4, 2};
r = to_nasal(c, test_data); r = c.to_nasal(test_data);
SGVec2f vec(0,2); SGVec2f vec(0,2);
r = to_nasal(c, vec); r = c.to_nasal(vec);
BOOST_CHECK_EQUAL(from_nasal<SGVec2f>(c, r), vec); BOOST_CHECK_EQUAL(c.from_nasal<SGVec2f>(r), vec);
std::vector<int> std_vec; std::vector<int> std_vec;
r = to_nasal(c, std_vec); r = c.to_nasal(std_vec);
r = to_nasal(c, "string"); r = c.to_nasal("string");
BOOST_CHECK_THROW(from_nasal<int>(c, r), bad_nasal_cast); BOOST_CHECK_THROW(c.from_nasal<int>(r), bad_nasal_cast);
Hash hash(c); Hash hash(c);
hash.set("vec", r); hash.set("vec", r);
@@ -171,10 +173,10 @@ BOOST_AUTO_TEST_CASE( cppbind_misc_testing )
it1 = it2; it1 = it2;
it3 = it2; it3 = it2;
r = to_nasal(c, hash); r = c.to_nasal(hash);
BOOST_REQUIRE( naIsHash(r) ); 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("vec"), "string");
BOOST_CHECK_EQUAL(string_map.at("name"), "my-name"); BOOST_CHECK_EQUAL(string_map.at("name"), "my-name");
BOOST_CHECK_EQUAL(string_map.at("string"), "blub"); BOOST_CHECK_EQUAL(string_map.at("string"), "blub");
@@ -260,81 +262,81 @@ BOOST_AUTO_TEST_CASE( cppbind_misc_testing )
Ghost<SGWeakRefBasedPtr>::init("SGWeakRefBasedPtr"); Ghost<SGWeakRefBasedPtr>::init("SGWeakRefBasedPtr");
SGWeakRefBasedPtr weak_ptr(new SGWeakReferenceBasedClass()); SGWeakRefBasedPtr weak_ptr(new SGWeakReferenceBasedClass());
naRef nasal_ref = to_nasal(c, weak_ptr), naRef nasal_ref = c.to_nasal(weak_ptr),
nasal_ptr = to_nasal(c, weak_ptr.get()); nasal_ptr = c.to_nasal(weak_ptr.get());
BOOST_REQUIRE( naIsGhost(nasal_ref) ); BOOST_REQUIRE( naIsGhost(nasal_ref) );
BOOST_REQUIRE( naIsGhost(nasal_ptr) ); BOOST_REQUIRE( naIsGhost(nasal_ptr) );
SGWeakRefBasedPtr ptr1 = from_nasal<SGWeakRefBasedPtr>(c, nasal_ref), SGWeakRefBasedPtr ptr1 = c.from_nasal<SGWeakRefBasedPtr>(nasal_ref),
ptr2 = from_nasal<SGWeakRefBasedPtr>(c, nasal_ptr); ptr2 = c.from_nasal<SGWeakRefBasedPtr>(nasal_ptr);
BOOST_CHECK_EQUAL(weak_ptr, ptr1); BOOST_CHECK_EQUAL(weak_ptr, ptr1);
BOOST_CHECK_EQUAL(weak_ptr, ptr2); BOOST_CHECK_EQUAL(weak_ptr, ptr2);
BOOST_REQUIRE( Ghost<BasePtr>::isInit() ); BOOST_REQUIRE( Ghost<BasePtr>::isInit() );
nasal::to_nasal(c, DoubleDerived2Ptr()); c.to_nasal(DoubleDerived2Ptr());
BasePtr d( new Derived ); BasePtr d( new Derived );
naRef derived = to_nasal(c, d); naRef derived = c.to_nasal(d);
BOOST_REQUIRE( naIsGhost(derived) ); BOOST_REQUIRE( naIsGhost(derived) );
BOOST_CHECK_EQUAL( std::string("DerivedPtr"), naGhost_type(derived)->name ); BOOST_CHECK_EQUAL( std::string("DerivedPtr"), naGhost_type(derived)->name );
// Get member function from ghost... // Get member function from ghost...
naRef thisGetter = naNil(); 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) ); BOOST_CHECK( naIsFunc(thisGetter) );
// ...and check if it really gets passed the correct instance // ...and check if it really gets passed the correct instance
typedef boost::function<unsigned long (Me)> MemFunc; 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_REQUIRE( fGetThis );
BOOST_CHECK_EQUAL( fGetThis(derived), (unsigned long)d.get() ); BOOST_CHECK_EQUAL( fGetThis(derived), (unsigned long)d.get() );
BasePtr d2( new DoubleDerived ); BasePtr d2( new DoubleDerived );
derived = to_nasal(c, d2); derived = c.to_nasal(d2);
BOOST_CHECK( naIsGhost(derived) ); BOOST_CHECK( naIsGhost(derived) );
BOOST_CHECK_EQUAL( std::string("DoubleDerivedPtr"), BOOST_CHECK_EQUAL( std::string("DoubleDerivedPtr"),
naGhost_type(derived)->name ); naGhost_type(derived)->name );
BasePtr d3( new DoubleDerived2 ); BasePtr d3( new DoubleDerived2 );
derived = to_nasal(c, d3); derived = c.to_nasal(d3);
BOOST_CHECK( naIsGhost(derived) ); BOOST_CHECK( naIsGhost(derived) );
BOOST_CHECK_EQUAL( std::string("DoubleDerived2Ptr"), BOOST_CHECK_EQUAL( std::string("DoubleDerived2Ptr"),
naGhost_type(derived)->name ); naGhost_type(derived)->name );
SGRefBasedPtr ref_based( new SGReferenceBasedClass ); 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( 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() ); 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_EQUAL( c.from_nasal<BasePtr>(derived), d3 );
BOOST_CHECK_NE( from_nasal<BasePtr>(c, derived), d2 ); BOOST_CHECK_NE( c.from_nasal<BasePtr>(derived), d2 );
BOOST_CHECK_EQUAL( from_nasal<DerivedPtr>(c, derived), BOOST_CHECK_EQUAL( c.from_nasal<DerivedPtr>(derived),
boost::dynamic_pointer_cast<Derived>(d3) ); 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::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; 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; 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; 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; 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 dict =
simgear::StringMap("hello", "value") simgear::StringMap("hello", "value")
("key2", "value2"); ("key2", "value2");
naRef na_dict = to_nasal(c, dict); naRef na_dict = c.to_nasal(dict);
BOOST_REQUIRE( naIsHash(na_dict) ); BOOST_REQUIRE( naIsHash(na_dict) );
BOOST_CHECK_EQUAL( Hash(na_dict, c).get<std::string>("key2"), "value2" ); 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); Hash obj(c);
obj.set("parents", parents); 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) // Check recursive parents (aka parent-of-parent)
std::vector<naRef> parents2; std::vector<naRef> parents2;
parents2.push_back(obj.get_naRef()); parents2.push_back(obj.get_naRef());
Hash derived_obj(c); Hash derived_obj(c);
derived_obj.set("parents", parents2); 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; std::vector<naRef> nasal_objects;
nasal_objects.push_back( Ghost<BasePtr>::makeGhost(c, d) ); 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, d2) );
nasal_objects.push_back( Ghost<BasePtr>::makeGhost(c, d3) ); 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[0], d );
BOOST_CHECK_EQUAL( objects[1], d2 ); BOOST_CHECK_EQUAL( objects[1], d2 );
BOOST_CHECK_EQUAL( objects[2], d3 ); BOOST_CHECK_EQUAL( objects[2], d3 );
{ // Calling fallback setter for unset values
// Calling fallback setter for unset values BOOST_CHECK_EQUAL( c.exec<int>("me.test = 3;", derived), 3 );
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());
BOOST_REQUIRE( !naGetError(c) ); // TODO real error check (this seems to // Calling generic (fallback) getter
// always return 0... BOOST_CHECK_EQUAL( c.exec<std::string>("var a = me.get_test;", derived),
BOOST_CHECK_EQUAL( from_nasal<int>(c, ret), 3 ); "generic-get" );
}
{
// 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" );
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Test nasal::CallContext // Test nasal::CallContext
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
int int_vec[] = {1,2,3}; int int_vec[] = {1,2,3};
std::map<std::string, std::string> map; std::map<std::string, std::string> map;
naRef args[] = { naRef args[] = {
to_nasal(c, std::string("test-arg")), c.to_nasal(std::string("test-arg")),
to_nasal(c, 4), c.to_nasal(4),
to_nasal(c, int_vec), c.to_nasal(int_vec),
to_nasal(c, map) c.to_nasal(map)
}; };
CallContext cc(c, naNil(), sizeof(args)/sizeof(args[0]), args); CallContext cc(c, naNil(), sizeof(args)/sizeof(args[0]), args);
BOOST_CHECK_EQUAL( cc.requireArg<std::string>(0), "test-arg" ); 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.isVector(2) );
BOOST_CHECK( cc.isHash(3) ); 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) ); BOOST_CHECK( naIsVector(args_vec) );
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Test nasal::String // Test nasal::String
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
String string( to_nasal(c, "Test") ); String string( c.to_nasal("Test") );
BOOST_CHECK_EQUAL( from_nasal<std::string>(c, string.get_naRef()), "Test" ); BOOST_CHECK_EQUAL( c.from_nasal<std::string>(string.get_naRef()), "Test" );
BOOST_CHECK_EQUAL( string.c_str(), std::string("Test") ); BOOST_CHECK_EQUAL( string.c_str(), std::string("Test") );
BOOST_CHECK( string.starts_with(string) ); BOOST_CHECK( string.starts_with(string) );
BOOST_CHECK( string.starts_with(String(c, "T")) ); 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, "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")), 0 );
BOOST_CHECK_EQUAL( string.find_first_not_of(String(c, "abc"), 20), String::npos ); 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");
} }
+1 -1
View File
@@ -25,7 +25,7 @@ static naGhostType ghost_type = {
static naRef createTestGhost(TestContext& c, intptr_t p) static naRef createTestGhost(TestContext& c, intptr_t p)
{ {
active_instances.insert(p); active_instances.insert(p);
return naNewGhost(c.c, &ghost_type, (void*)p); return naNewGhost(c, &ghost_type, (void*)p);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
+15 -10
View File
@@ -1,3 +1,6 @@
///@file
/// The Nasal scripting language
///
#ifndef _NASAL_H #ifndef _NASAL_H
#define _NASAL_H #define _NASAL_H
#ifdef __cplusplus #ifdef __cplusplus
@@ -15,12 +18,14 @@ extern "C" {
#define GCC_PURE #define GCC_PURE
#endif #endif
/** Nasal context pointer */
typedef struct Context* naContext; 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); 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) typedef naRef (*naCFunctionU)
(naContext ctx, naRef me, int argc, naRef* args, void* user_data); (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_cset(naRef hash, char* key, naRef val);
void naHash_delete(naRef hash, naRef key); 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 * @see ::naNewVector
*/ */
@@ -273,25 +278,25 @@ typedef struct naGhostType {
} naGhostType; } naGhostType;
/** /**
* Create a ghost for an object without any attributes. If ::t contains pointers * Create a ghost for an object without any attributes. If @p t contains
* to get_member or set_member function they will be ignored. * pointers to get_member or set_member function they will be ignored.
*/ */
naRef naNewGhost(naContext c, naGhostType* t, void* ghost); naRef naNewGhost(naContext c, naGhostType* t, void* ghost);
/** /**
* Create a ghost for an object. This version uses the get_member and set_member * 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 * function pointers in @p t upon trying to get or set a member respectively
* Nasal. * from Nasal.
*/ */
naRef naNewGhost2(naContext c, naGhostType* t, void* ghost); naRef naNewGhost2(naContext c, naGhostType* t, void* ghost);
naGhostType* naGhost_type(naRef ghost); naGhostType* naGhost_type(naRef ghost);
void* naGhost_ptr(naRef ghost); void* naGhost_ptr(naRef ghost);
/** /**
* Attach a nasal object to the given ghost. Binds the lifetime of @a data to * Attach a nasal object to the given ghost. Binds the lifetime of @p data to
* the lifetime of the @a ghost. * the lifetime of the @p ghost.
*/ */
void naGhost_setData(naRef ghost, naRef data); 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(). * naGhost_setData().
*/ */
naRef naGhost_data(naRef ghost); naRef naGhost_data(naRef ghost);