I am experiencing an issue with passing string properties as "const string& inout" references in AngelScript. On CPP side the string properties are defined as "std::string" instances. On AngelScript side I want to use the "CScriptString" add-on to pass strings by reference and to have the extended numeric conversion support. Therefore I have defined the following wrapper templates, which allow to register the string properties with the AngelScript engine. The wrappers take care of the conversion between "CScriptString" and "std::string".
// Accessor wrapper for string properties.template <class Type, std::string Type::* Member>struct StringPropertyWrapper{ // Retrieves the string property as a cscriptstring handle static CScriptString* get(Type* object) { return new CScriptString(object->*Member); } // Assignes the string property from a cscriptstring handle static void set(const CScriptString* string, Type* object) { object->*Member = string->buffer; }};// Accessor wrapper for string properties.template <class Type, const std::string& (Type::*Getter)() const, void (Type::*Setter)(const std::string&)>struct StringPropertyAccessorWrapper{ // Retrieves the string property as a cscriptstring handle static CScriptString* get(Type* object) { return new CScriptString((object->*Getter)()); } // Assignes the string property from a cscriptstring handle static void set(const CScriptString* string, Type* object) { (object->*Setter)(string->buffer); }};
To improve the registration workflow I have additionally defined the following two macros. The macros allow to register the respecitve string properties with one short line as compared to two long lines of code.
// Register the getter and setter wrapper#define REGISTER_STRING_PROPERTY(engine, type, name, class, member) assert(mEngine->RegisterObjectMethod(type, std::string("const string& get_").append(name).append("() const").c_str(), asFunctionPtr(StringPropertyWrapper<class, &class::member>::get), asCALL_CDECL_OBJLAST) >= 0); assert(mEngine->RegisterObjectMethod(type, std::string("void set_").append(name).append("(const string& in)").c_str(), asFunctionPtr(StringPropertyWrapper<class, &class::member>::set), asCALL_CDECL_OBJLAST) >= 0);// Register the getter and setter wrapper#define REGISTER_STRING_PROPERTY_ACCESSORS(engine, type, name, class, getter, setter) assert(mEngine->RegisterObjectMethod(type, std::string("const string& get_").append(name).append("() const").c_str(), asFunctionPtr(StringPropertyAccessorWrapper<class, &class::getter, &class::setter>::get), asCALL_CDECL_OBJLAST) >= 0); assert(mEngine->RegisterObjectMethod(type, std::string("void set_").append(name).append("(const string& in)").c_str(), asFunctionPtr(StringPropertyAccessorWrapper<class, &class::getter, &class::setter>::set), asCALL_CDECL_OBJLAST) >= 0);
So far everything seems to work fine, the accessor wrappers are called with the correct values and the effects are reflected properly. Next I defined a function with a "const string& inout" parameter
void test(const string&)
and issued the call
test(object.property)
where the access to "object.property" is actually handled by the wrapper functions. The behavior that I encounter here is that the function parameter is not initialized with the object property. Actually the getter of the property isn't executed at all. I was wondering if this behavior is intended. Originally I was expecting first a get-call, the the test function call and finally a set call.
Thanks for your help.
Cheers,
Georg
[Edited by - ghackenberg on July 15, 2010 5:38:38 AM]