since I already got valuable feedback from you about the string issue (thread link) I wanted to start the discussion about another topic as well: "boost::shared_ptr". We use shared pointers in our application a lot, e.g. as return values of manager objects or as parameters to function calls. To make the application interface scriptable we decided to try wrapping the "boost::shared_ptr" class in AngelScript. What I came up with look like the following:
First a wrapper for constructing and desctructing shared pointer objects is defined
/// \brief Wrapper template for shared pointer behavior.template <typename Type>struct SharedPointerWrapper{ /// \brief Constructor wrapper. static void construct(void* memory); /// \brief Destructor wrapper. static void destruct(void* memory);};template <typename Type>void SharedPointerWrapper<Type>::construct(void* memory){ new(memory) boost::shared_ptr<Type>();}template <typename Type>void SharedPointerWrapper<Type>::destruct(void* memory){ ((boost::shared_ptr<Type>*)memory)->~shared_ptr();}
Then I have a registration function, which looks as follows. Note that shared pointers are registered as value type with constructor/destructor and assignment operators. Finally, also a "get" method is provided to retrieve a reference to the contained object. The boost implementation of the get method just returns the raw pointer.
/// \brief Function template for registering shared pointer types.template <typename Type>void RegisterSharedPointer(const Core::String& ptrTypeName, const Core::String& typeName, asIScriptEngine* engine){ Core::String getSignature; getSignature.append(typeName).append("& get()"); int r; r = engine->RegisterObjectType(ptrTypeName.c_str(), sizeof(boost::shared_ptr<Type>), asOBJ_VALUE | asOBJ_APP_CLASS_CDA); assert(r >= 0); r = engine->RegisterObjectBehaviour(ptrTypeName.c_str(), asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(SharedPointerWrapper<Type>::construct), asCALL_CDECL_OBJLAST); assert(r >= 0); r = engine->RegisterObjectBehaviour(ptrTypeName.c_str(), asBEHAVE_DESTRUCT, "void f()", asFUNCTION(SharedPointerWrapper<Type>::destruct), asCALL_CDECL_OBJLAST); assert(r >= 0); r = engine->RegisterObjectMethod(ptrTypeName.c_str(), (ptrTypeName + "& opAssign(const " + ptrTypeName + " ∈ other)").c_str(), asMETHODPR(boost::shared_ptr<Type>, operator=, (boost::shared_ptr<Type> const &), boost::shared_ptr<Type>&), asCALL_THISCALL); assert(r >= 0); r = engine->RegisterObjectMethod(ptrTypeName.c_str(), getSignature.c_str(), asMETHOD(boost::shared_ptr<Type>, get), asCALL_THISCALL); assert(r >= 0);}
Now I can register "boost::shared_ptr" classes as follows:
RegisterSharedPointer<Type>("TypePtr", "Type", engine);
Before executing that line I have to make sure that the type "Type" has been registered on the engine. Since I only want AngelScript code to remember the shared pointer object I currently register the contained type as "asOBJ_REF | asOBJ_SCOPED", i.e.:
engine->RegisterObjectType("Type", 0, asOBJ_REF | asOBJ_SCOPED);engine->RegisterObjectMethod("Type", "string getProperty()", ...);
This finally allows me to write the following in AngelScript:
TypePtr shared = manager.getSomeSharedTypeInstance();print(shared.get().getProperty());
So far the concept does not seem to crash or memory-leak. It also seems to be possible to pass shared pointer instances allocated by AngelScript back to CPP, i.e.
anotherManager.use(shared);
I was wondering what you think about this issue.
Regards,
Georg