Skip to main content
gamedev.net
🔒 Locked

Returning a class

Started by Black Dot 6 replies 1.5k views
Original Post
Black Dot
Black Dot
Hello! I wanted to write code which will handle such operations in the script: CSomeClass class; class = Master.FindSub(...); I don't know if I did that properly, because I'm receiving some not very pleasant errors. Here is what I did: Master class:

class CMaster
{
public:
	CMaster(){};
	~CMaster(){};

	CSomeClass FindSub( int index )
	{
		CSomeClass cl;
		return cl;
	}
};
Here I register CSomeClass:

	r = ScriptEngine->RegisterObjectType("CSomeClass", sizeof(CSomeClass), asOBJ_CLASS_CDA);assert(r>=0);
	r=ScriptEngine->RegisterObjectBehaviour("CSomeClass", asBEHAVE_CONSTRUCT, "void f()", asFUNCTIONPR(Constructor, (CSomeClass*), void), asCALL_CDECL_OBJLAST); assert(r >= 0);
	r=ScriptEngine->RegisterObjectBehaviour("CSomeClass", asBEHAVE_DESTRUCT, "void f()", asFUNCTIONPR(Destructor, (CSomeClass&), void), asCALL_CDECL_OBJLAST); assert(r >= 0);
	r=ScriptEngine->RegisterObjectBehaviour("CSomeClass", asBEHAVE_ADDREF, "void f()", asMETHOD(CSomeClass, AddRef), asCALL_THISCALL); assert(r >= 0);
	r=ScriptEngine->RegisterObjectBehaviour("CSomeClass", asBEHAVE_RELEASE, "void f()", asMETHOD(CSomeClass, Release), asCALL_THISCALL); assert(r >= 0);
Here is it's declaration:

class CSomeClass
{
public:	
	CSomeClass(): refcount(1) {};
	~CSomeClass()
	{
	}
	void AddRef(){refcount++;}
	void Release(){ if(--refcount == 0) delete this;}
private:
	int refcount;
};
Here I register the CMaster class:

	r = ScriptEngine->RegisterObjectType("CMaster",sizeof(CMaster), asCALL_CDECL);assert(r >= 0);
	r = ScriptEngine->RegisterGlobalProperty("CMaster Master", (void*)&Master); assert(r>=0);
	r = ScriptEngine->RegisterObjectMethod("CMaster", "CSomeClass FindSub(int index)", asMETHOD(CMaster,FindSub), asCALL_THISCALL);assert(r >= 0);
Then when I perform: CSomeClass class; class = Master.FindSub(...); I get some heap allocation errors. P.S. I hope I remembered to put everything that is of any use here. Regards, Black Dot
Falling Man GamesFeel free to visit us!
WitchLord
WitchLord
You cannot use reference counting with objects allocated on the stack, nor can you pass reference counted objects by value or return them by value.

Change your FindSub() to:

CSomeClass *FindSub(int index){  return new CSomeClass();}


Also register the method with:

r = ScriptEngine->RegisterObjectMethod("CMaster", "CSomeClass@ FindSub(int index)", asMETHOD(CMaster,FindSub), asCALL_THISCALL); assert(r >= 0);


This should be the only thing you need to change to get things working.

Regards,
Andreas
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - <a href="http://www.angelcode.com/tower" rel
Deyja
Deyja
Quote:
class = Master.FindSub(...);


It might just seem to be working correctly. You didn't bind an operator=, but you are using it.
WitchLord
WitchLord
Well spotted!

The assignment behaviour is indeed a must when using reference counting. Without it AngelScript will just do a bit-by-bit copy of the objects, overwriting any reference counters, which will lead to problems later on.

I'll change the way objects are registered to have the engine detect when behaviours aren't registered. It will still be possible to use the default behaviour, but it has to be a conscious choice.

Regards,
Andreas
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - <a href="http://www.angelcode.com/tower" rel
Rain Dog
Rain Dog
I was thinking that that might be the case, but Black Dot told me that everything was working fine afterwards.

It seemed strange to me that you can do this in C++

 using namespace std;    class MyClass  {  public:       MyClass() : refcount(1){};       ~MyClass(){};         void AddRef(){refcount++;}       void Release()       {            if(--refcount == 0)                 delete this;       }         int GetRefcount(){return refcount;}         void PrintMessage()       {            cout << "this is a message" << endl;       }  private:       int refcount;  };    MyClass GetMyClass()  {       MyClass f;       return f;  }      int _tmain(int argc, _TCHAR* argv[])  {       MyClass f = GetMyClass();       cout << f.GetRefcount() << endl;       f.PrintMessage();       system("pause");       return 0;  } 


But if you tried the same thing in AS it would fail.
Deyja
Deyja
You can do that in anglescript. You did
myclass instance = new_instance;

He did
myclass instance = default_instance;instance = new_instance;

The first compiles in C++ because it doesn't call operator=. It still isn't any good if you don't have a proper copy constructor.
WitchLord
WitchLord
In the C++ function the object is allocated on the stack, but in AngelScript objects are allocated on the heap. Thus, when AngelScript receives the object from the C++ function it will call the Release() method to free the object, which in turn will call delete on the object pointer. Delete on objects allocated on the stack may result in unexpected behaviour, maybe even crash the application.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - <a href="http://www.angelcode.com/tower" rel

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.