Jump to content
  • Advertisement
Sign in to follow this  
Black Dot

Returning a class

This topic is 4847 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
Advertisement
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

Share this post


Link to post
Share on other sites
Quote:
class = Master.FindSub(...);


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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!