When to use asOBJ_POD

Started by
7 comments, last by WitchLord 10 years, 2 months ago

I'm binding an existing C++ struct as a value type. The struct has (as members) a couple of vectors (all float members), a color (an int member), a couple of floats and a bool. So, in the end, all primitives, no pointers.

I bind the type with these flags: asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CK

Should I be using asOBJ_POD for this type?

The documentation says:

In this case AngelScript doesn't require the default constructor, assignment behaviour, or destructor as it will be able to automatically handle these cases the same way it handles built-in primitives.

However, since this struct has a non-default constructor, I've already provided the typical placement-new constructor, along with this other constructor which takes some parameters. If I've provided the constructor already.. does that conflict with asOBJ_POD?

Thank you!

Advertisement

Basically you'll want to use asOBJ_POD for any C++ type that is a plain-old-data type, i.e. doesn't have any virtual function table, and doesn't have any members that require explicit initialization and/or clean-up (e.g. pointers, file handle ids, etc).

There is no problem in providing constructors for objects registered with asOBJ_POD. The flag just says they are not required, not that they are not allowed. Without the asOBJ_POD flag, AngelScript would require the application to register both constructor (at least one) and destructor for the object.

The use of asOBJ_POD also allows AngelScript to make some optimizations, as it can safely inline POD objects within script classes without worrying about invalid memory access due to uninitialized objects while executing the script class constructor.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

So if my C++ struct has some user-defined ctors, I guess by definition it is not a POD type. So I wouldn't want to use asOBJ_POD if I was binding it as a value type, correct?

In that case I'd have to provide a destructor helper, correct? If I don't otherwise have a user-defined dtor in the C++ struct, would I want to have this helper be an empty function (and use asOBJ_APP_CLASS_CAK), or should I actually call the dtor of the C++ struct (making the compiler create a definition for one) and use AS_OBJ_APP_CLASS_CDAK?

Thank you.

In this topic, you say:

It is all related to the native calling convention. In your first test you hadn't registered the Integer class correctly, which is why you were getting the wrong result. The original declaration should be registered with the flags asOBJ_APP_CLASS_C, not asOBJ_APP_CLASS_CK as it didn't have an explicit copy constructor.

When you explicitly declared the copy constructor in the Integer class the result was corrected as now the flag asOBJ_APP_CLASS_CK was correct.

But in the documentation for registering a value type, you say:

Observe that the C++ compiler may provide these functions automatically if one of the members of the class is of a type that requires it. So even if the type you want to register doesn't have a declared default constructor it may still be necessary to register the type with the flag asOBJ_APP_CLASS_CONSTRUCTOR. The same for the other functions.

I understand that some compilers treat C++ classes very differently depending on whether there's an explicit copy ctor. However.. the documentation makes it sound like e.g. if my class doesn't have an explicit assignment operator, but I've registered opAssign(), then the compiler is going to create one for me... so I should set the flag appropriately? Is the copy ctor the only one that should be based on whether you have an explicit one?

The existance of a user defined constructor doesn't imply that that the object is not a POD type. If the members can be safely accessed even before the constructor is called without causing any harm, then it can still be considered a POD type.

For example:

class Vec2
{
public:
   Vec2() : x(0), y() {}
   Vec2(float _x, float _y) : x(_x), y(_y) {}
   float x,y;
}

The above class is an ordinary POD type even though it has user defined constructors. Think of it like this. Can any harm be done if you interpret a random address into uninitialized memory as the type and then access the members? If no harm can be done then the type is a POD type, but if some harm can be done then it is not a POD type.

asOBJ_POD and the various asOBJ_APP_CLASS_ flags are not directly related to each other. The first tells AngelScript that it is safe to access the unitialized memory and thus it can allow direct bitwise copies of the objects, and the second is used to allow AngelScript to properly passed values of the type to the application registered functions in native calling conventions.

Ideally you would use the templated GetTypeTraits<T>() helper add-on function to determine the correct combination of the asOBJ_APP_CLASS_ flags automatically. This function is only available for compilers that support C++11 though, so if you use an older compiler you'll need to determine the flags manually.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Thank you very much for the detailed response.

Regarding the asOBJ_APP_CLASS_ flags and the difference between explicit and implied ctors.. are there any guidelines to know when the presence of compiler-provided functions means I should specify that in the asOBJ_APP_CLASS_ flags, and when I should not? Considering that I'm on 32-bit linux anyway and everything seems to be working... should I just leave it alone?

gcc is c++11 capable (from 4.7+) if you compile with -std=c++11 so I suggest you use the GetTypeTraits, this way you don't have to worry about informing the wrong flags by mistake.

Example:

#include <add_on/scripthelper/scripthelper.h>
 
engine->RegisterObjectType("vector3", sizeof(vector3), asOBJ_VALUE | asOBJ_POD | GetTypeTraits<vector3>());

Otherwise, the guidelines for determining the correct flags, are those written in the manual.

On 32bit Linux only the existance of the class destructor or the class copy constructor influences the native calling convention, but on other platforms other properties of the class influences it, so if you're planning on porting your code to other platforms in the future try to set the flags correctly to avoid head-aches later on.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

GetTypeTraits() isn't available to me quite yet (I'm on gcc 4.6, not 4.7).

When you say "the existance of the class destructor or the class copy constructor", do you mean explicit/user-defined ones, or even compiler-generated ones?

(Not meaning to be picky, just trying to understand.)

Thanks!!!

Perhaps a couple of examples will help.

class vector2
{
public:
   vector2();  // explicit default constructor
   vector2(const vector2 &); // explicit copy constructor
 
   float x,y;
};
 
class data
{
public:
   data();
 
   std::string name;
}

The vector2 class should be registered with the flags asOBJ_APP_CLASS_CK because it has a default constructor and a copy constructor.

The data class should be registered with the flags asOBJ_APP_CLASS_CD because it has a default constructor and an implicit destructor due to the string member.

Ideally you would also make a controlled test with the type after registering it. Try for example to call an application registered function that takes or returns the type by value and see if the object is correctly passed between AngelScript and the application. If it is not correct the result may either be a segfault or simply garbage in the members.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement