typedef boost::function<naRef(naContext, raw_type&)> getter_t;
typedef boost::function<void(naContext, raw_type&, naRef)> setter_t;
typedef boost::function<naRef(raw_type&, const CallContext&)> method_t;
+ typedef boost::function<bool( naContext,
+ raw_type&,
+ const std::string&,
+ naRef& )> fallback_getter_t;
typedef boost::function<bool( naContext,
raw_type&,
const std::string&,
if( !_fallback_setter )
_fallback_setter = base->_fallback_setter;
+ if( !_fallback_getter )
+ _fallback_getter = base->_fallback_getter;
return *this;
}
return *this;
}
+ /**
+ * Register a function which is called upon retrieving an unknown member
+ * of this ghost.
+ */
+ Ghost& _get(const fallback_getter_t& getter)
+ {
+ _fallback_getter = getter;
+ return *this;
+ }
+
+ /**
+ * Register a method which is called upon retrieving an unknown member of
+ * this ghost.
+ *
+ * @code{cpp}
+ * class MyClass
+ * {
+ * public:
+ * bool getMember( const std::string& key,
+ * std::string& value_out );
+ * }
+ *
+ * Ghost<MyClassPtr>::init("Test")
+ * ._get(&MyClass::getMember);
+ * @endcode
+ */
+ template<class Param>
+ Ghost& _get(bool (raw_type::*getter)(const std::string&, Param&))
+ {
+ return _get(boost::bind(
+ convert_param_invoker<Param>, getter, _1, _2, _3, _4
+ ));
+ }
+
+ /**
+ * Register a method which is called upon retrieving an unknown member of
+ * this ghost.
+ *
+ * @code{cpp}
+ * class MyClass
+ * {
+ * public:
+ * bool getMember( naContext c,
+ * const std::string& key,
+ * naRef& value_out );
+ * }
+ *
+ * Ghost<MyClassPtr>::init("Test")
+ * ._get(&MyClass::getMember);
+ * @endcode
+ */
+ Ghost& _get(bool (raw_type::*getter)( naContext,
+ const std::string&,
+ naRef& ))
+ {
+ // Getter signature: bool( naContext,
+ // raw_type&,
+ // const std::string&,
+ // naRef& )
+
+ return _get( boost::bind(getter, _2, _1, _3, _4) );
+ }
+
/**
* Register a function which is called upon setting an unknown member of
* this ghost.
);
}
+ /**
+ * Invoke a method which writes the converted parameter to a reference
+ */
+ template<class Param>
+ static
+ bool convert_param_invoker
+ (
+ const boost::function<bool ( raw_type&,
+ const std::string&,
+ Param& )>& func,
+ naContext c,
+ raw_type& obj,
+ const std::string& key,
+ naRef& out
+ )
+ {
+ Param p;
+ if( !func(obj, key, p) )
+ return false;
+
+ out = to_nasal(c, p);
+ return true;
+ };
/**
* Invoke a method which returns a value and convert it to Nasal.
typedef std::auto_ptr<Ghost> GhostPtr;
MemberMap _members;
+ fallback_getter_t _fallback_getter;
fallback_setter_t _fallback_setter;
explicit Ghost(const std::string& name):
getSingletonPtr()->_members.find(key_str);
if( member == getSingletonPtr()->_members.end() )
- return 0;
-
- if( member->second.func )
+ {
+ fallback_getter_t fallback_get = getSingletonPtr()->_fallback_getter;
+ if( !fallback_get
+ || !fallback_get(c, *getRawPtr(g), key_str, *out) )
+ return 0;
+ }
+ else if( member->second.func )
*out = member->second.func->get_naRef(c);
else if( !member->second.getter.empty() )
*out = member->second.getter(c, *getRawPtr(g));
{
return key == "test";
}
+ bool genericGet(const std::string& key, std::string& val_out)
+ {
+ if( key != "get_test" )
+ return false;
+
+ val_out = "generic-get";
+ return true;
+ }
};
void baseVoidFunc(Base& b) {}
.method("bool2args", &Base::test2Args)
.method("str_ptr", &testPtr)
.method("this", &Base::getThis)
- ._set(&Base::genericSet);
+ ._set(&Base::genericSet)
+ ._get(&Base::genericGet);
Ghost<DerivedPtr>::init("DerivedPtr")
.bases<BasePtr>()
.member("x", &Derived::getX, &Derived::setX)
VERIFY( objects[1] == d2 );
VERIFY( 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());
-
- VERIFY( !naGetError(c) ) // TODO real error check (this seems to always
- // return 0...
- VERIFY( from_nasal<int>(c, ret) == 3 )
+ {
+ // 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());
+
+ VERIFY( !naGetError(c) ) // TODO real error check (this seems to always
+ // return 0...
+ VERIFY( 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());
+
+ VERIFY( !naGetError(c) ) // TODO real error check (this seems to always
+ // return 0...
+ VERIFY( from_nasal<std::string>(c, ret) == "generic-get" );
+ }
//----------------------------------------------------------------------------
// Test nasal::CallContext