If the type will be passed to and from the application by value using native calling conventions, it is important to inform AngelScript of its real type in C++, otherwise AngelScript won't be able to determine exactly how C++ is treating the type in a parameter or return value.
There are a few different flags for this:
asOBJ_APP_CLASS | The C++ type is a class, struct, or union |
asOBJ_APP_CLASS_CONSTRUCTOR | The C++ type has a defined constructor |
asOBJ_APP_CLASS_DESTRUCTOR | The C++ type has a defined destructor |
asOBJ_APP_CLASS_ASSIGNMENT | The C++ type has a defined assignment operator |
asOBJ_APP_PRIMITIVE | The C++ type is a C++ primitive, but not a float or double |
asOBJ_APP_FLOAT | The C++ type is a float or double |
Note that these don't represent how the type will behave in the script language, only what the real type is in the host application. So if you want to register a C++ class that you want to behave as a primitive type in the script language you should still use the flag asOBJ_APP_CLASS. The same thing for the flags to identify that the class has a constructor, destructor, or assignment. These flags tell AngelScript that the class has the respective function, but not that the type in the script language should have these behaviours.
For class types there are also a shorter form of the flags for each combination of the 4 flags. They are of the form asOBJ_APP_CLASS_CDA, where the existance of the last letters determine if the constructor, destructor, and/or assignment behaviour are available. For example asOBJ_APP_CLASS_CDA is defined as asOBJ_APP_CLASS | asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT.
// Register a primitive type, that doesn't need any special management of the content r = engine->RegisterObjectType("pod", sizeof(pod), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 ); // Register a class that must be properly initialized and uninitialized r = engine->RegisterObjectType("val", sizeof(val), asOBJ_VALUE | asOBJ_APP_CLASS_CDA); assert( r >= 0 );
void Constructor(void *memory) { // Initialize the pre-allocated memory by calling the // object constructor with the placement-new operator new(memory) Object(); } void Destructor(void *memory) { // Uninitialize the memory by calling the object destructor ((Object*)memory)->~Object(); } // Register the behaviours r = engine->RegisterObjectBehaviour("val", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Constructor), asCALL_CDECL_OBJLAST); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("val", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );
The assignment behaviour is registered the same way as for reference types.