🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Class Constructors

Started by
11 comments, last by WitchLord 19 years, 2 months ago
How can I prevent AngelScript from allowing the use of a class that has no default constructor without arguments? My class has a constructor with an argument (unsigned int).
result = engine->RegisterObjectBehaviour
(
	"Class",
	asBEHAVE_CONSTRUCT,
	"void f(uint val)",
	asFUNCTION(ConstructClass),
	asCALL_CDECL_OBJFIRST
);
Yet AngelScript still allows:
Class cls;
When only
Class cls(1);
Should work. Is there any way to enforce this? I thought of registering a constructor with no arguments, then throwing an error, but I would prefer this to be a build time error, not a runtime error.
Advertisement
Hmm, I never thought about this case. There is currently no way to do what you want.

The biggest problem is that the compiler internally uses the default constructor to create temporary objects, e.g. when calling a function that returns an object of the type in a parameters. If you remove the possibility of using the default constructor (for example by raising an exception in the constructor), then it may cause problems that could be difficult to resolve.

I have to think about how to best solve this case. Unfortunately there is no immediately apparent solution.

For now I suggest you make the default constructor choose a default value for the parameter and initialize the object using that one, e.g. Class cls leads to Class(1) being called.



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

WitchLord:
Do you plan to add support for non-default constructors in the future?

[Edited by - bozho on April 27, 2005 9:25:20 AM]
WitchLord:
Just an idea about non-default constructors... My idea of an ideal solution would be something like this:
class A {   public:      A(int a, float b);      Construct(int a, float b);};A::A(int a, float b) {...}A::Construct(int a, float b, A* instance) {   new(instance) A(a, b);}

After that, register A::Construct as constructor for scripts, and AS compiler might translate lines like:
// script codeA a(1, 0.0);

into calls to A::Construct. Could this be done?

BTW, is it currently possible to register a class method as constructor for scripts? I've tried it, but it didn't work.

Non-default constructors are already supported. Example:

// C++ codevoid Construct(int param, object *o){  new(o) object(param);}engine->RegisterObjectBehaviour("object", asBEHAVE_CONSTRUCT, "void f(int)", asFUNCTION(Construct), asCALL_CDECL_OBJLAST);// AngelScript codeobject o(234);


You can register a method as a constructor (unless there is a bug), but it cannot be a virtual method, as part of the constructor's job is to initialize the virtual function table in the class.

Regards,
Andreas

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

Which calling convention do I use? I've tried both asCALL_THISCALL and asCALL_CDECL_OBJLAST, but I get ESP error... Maybe I'm doing something wrong. I'll try it with a minimal example tomorrow.

Thanks for your help :)
The calling convention depends on the function you register. A class method should be registered with asCALL_THISCALL calling convention. A global function acting as class method should be registered with asCALL_CDECL_OBJLAST or asCALL_CDECL_OBJFIRST.

The ESP problem can depend on calling convention, but can also depend on the function declaration you passed to the library.

Show me the functions implementation (at least it's parameters) and how you registered it and I might be able to tell you what's wrong.

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

Ok... Here's the minimal code I'm using:
class Test2 {   public:      Test2(int a, int b);      virtual ~Test2();      void Constructor(int a, int b, Test2* instance);   public:      static void AngelScriptRegister(asIScriptEngine* pEngine);   public:      int m_nA;      int m_nB;};...void Test2::Constructor(int a, int b, Test2* instance) {   new(instance) Test2(a, b);}

I've tried to register Constructor as:
r = pEngine->RegisterObjectBehaviour(               "Test2",                asBEHAVE_CONSTRUCT,                "void Constructor(int a, int b)",                asMETHOD(Test2, Constructor),                asCALL_THISCALL);


Constructor is called, but I get ESP error. Then I tried:
r = pEngine->RegisterObjectBehaviour(               "Test2",                asBEHAVE_CONSTRUCT,                "void Constructor(int a, int b, Test2∈)",                asMETHOD(Test2, Constructor),                asCALL_THISCALL);

In this case, return code (r) is ok, but Constructor isn't called. Then I tried with handles (AddRef and Release are registered):
r = pEngine->RegisterObjectBehaviour(               "Test2",                asBEHAVE_CONSTRUCT,                "void Constructor(int a, int b, Test2@)",                asMETHOD(Test2, Constructor),                asCALL_THISCALL);

Again, Constructor is not called (return value r was ok)

Is there a combination I haven't tried? :)

Thnx

Witchlord,

In the case of classes with no defualt constructors registered, why not simply treat it as a compilation error? That is, prevent the declaration of variables like:

Object myObject; // no params

As for static object assignment, aren't those catered for by the assignment operator and copy constructors with a default bitwise copy as a backup?

Maybe I'm missing something obvious here.. if so, please bear with me :)
tIDE Tile Map Editorhttp://tide.codeplex.com
bozho:

Since you are registering the constructor as a class method, the object pointer will be available in the this pointer. It will not be passed as a parameter. Thus you ought to implement it like this:

class Test2 {   public:      Test2(int a, int b);      virtual ~Test2();      void Constructor(int a, int b);   public:      static void AngelScriptRegister(asIScriptEngine* pEngine);   public:      int m_nA;      int m_nB;};...void Test2::Constructor(int a, int b) {   new(this) Test2(a, b);}


The constructor should be registered as follows (your first option):

r = pEngine->RegisterObjectBehaviour(               "Test2",                asBEHAVE_CONSTRUCT,                "void Constructor(int a, int b)",                asMETHOD(Test2, Constructor),                asCALL_THISCALL);


This constructor will only be called if the script explicitly declares the object with the two parameters:

Test2 a(1,2); // Calls your constructorTest2 b;      // Calls the default constructor (which is not registered in the example above, causing an uninitialized object)


SharkBait:

There are times when AngelScript needs to be able to create a default object (implicitly) without copying another. When passing an object to a parameter marked as &out, is one such situation. Thus AngelScript will not work correctly if the default constructor isn't registered.

Of course, I could have the compiler make an error in this case, and it might even be the best thing to do. But then the application will have to register a default constructor for all objects it registers (unless it really shouldn't have one).

If the object type is registered with a size of zero, then the script cannot use any constructor to declare the object locally. It could be used to prevent the use of the default constructor, but then it would have to be manipulated through handles, and factory functions would be needed to create the objects and return their handles.

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