Jump to content
  • Advertisement
Sign in to follow this  
Budskii

Difference between object handles/references

This topic is 1007 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

Ok, so I've just start using Angelscript recently and absolutely love it. Have a question on something i'm confused about

 

I've registered an object like this:

 

r = scriptEngine->RegisterObjectType("CTimer", 0, asOBJ_REF); assert( r >= 0 );
r = scriptEngine->RegisterObjectBehaviour("CTimer", asBEHAVE_ADDREF, "void f()", asMETHOD(CTimer, AddRef), asCALL_THISCALL); assert( r >= 0 );
r = scriptEngine->RegisterObjectBehaviour("CTimer", asBEHAVE_RELEASE, "void f()", asMETHOD(CTimer, ReleaseRef), asCALL_THISCALL); assert( r >= 0 );
r = scriptEngine->RegisterObjectBehaviour("CTimer", asBEHAVE_FACTORY, "CTimer@ f()", asFUNCTION(Scr_CTimer_Factory), asCALL_CDECL); assert( r >= 0 );
 
I can't seem to find anything in documentation or forums about the differences between references and object handles. From what I understand from a C++/memory perspective is that they are both pointers. I also understand that a reference cannot be null and a object handle can be. Apart from that what is the difference between them say when i'm using CTimer object.
 
I've switched all the &'s to @ and everything works just fine. 

Share this post


Link to post
Share on other sites
Advertisement

The difference between a reference and handle in AngelScript is pretty much the same as the difference between a reference and a pointer in C++.

 

You already stated one of the differences: "I also understand that a reference cannot be null and a object handle can be".

 

Another difference is that a reference cannot be reassigned to point to a different object while an handle can be.

 

 

When registering functions with AngelScript you'll have to be careful with the choice of reference versus handle due to the reference counting. When registering the function as returning a reference, the C++ function must not increment the ref counter of the object, but when registering the function as returning a handle, the C++ function must increment the ref counter of the object (or use auto handles to tell AngelScript to do that for you). If you don't do this correctly you may end up with memory leaks, or crashes due to the objects being freed too early.

Share this post


Link to post
Share on other sites

The difference between a reference and handle in AngelScript is pretty much the same as the difference between a reference and a pointer in C++.

 

You already stated one of the differences: "I also understand that a reference cannot be null and a object handle can be".

 

Another difference is that a reference cannot be reassigned to point to a different object while an handle can be.

 

 

When registering functions with AngelScript you'll have to be careful with the choice of reference versus handle due to the reference counting. When registering the function as returning a reference, the C++ function must not increment the ref counter of the object, but when registering the function as returning a handle, the C++ function must increment the ref counter of the object (or use auto handles to tell AngelScript to do that for you). If you don't do this correctly you may end up with memory leaks, or crashes due to the objects being freed too early.

 

Thank you for the reply.

 

I registered a callback like this:

r = scriptEngine->RegisterFuncdef("void CTimerCallback(CTimer@)");

In a script I made this function:

void DoRandomStuff(CTimer@ timer)
{
Print("Well this is great\n");
}
I made a new CTimer in C++ and initliazed its refCount to 1 and then called DoRandomStuff() from C++ but this did not reduce the refCount. I'm assuming refCount is supposed to be reduced by the function caller and not the function called?
 
This will be a bit more work I guess, you would have to call C++ script functions and after it is done executing releaseRef() yourself manually
 
Also, a question regarding this script;

CTimer timer;
CTimer@ timer_handle = @timer;


void DoRandomStuff(CTimer@ timer)
{
Print("Well this is great\n");
}

 

that all makes sense, but if you need to pass that handle (timer_handle) which was declared to be  a handle onto another function do you need to use @?

 

so should it be:

DoRandomStuff(timer_handle);

or

DoRandomStuff(@timer_handle);

They both work and script runs fine but I'm wondering if there is any different between the two?

Edited by Budskii

Share this post


Link to post
Share on other sites

Earlier I said "I'm assuming refCount is supposed to be reduced by the function caller and not the function called?"

I decided to test this out in a script, I added logging AddRef() ReleaseRef() and Constructor functions in the CTimer class

 

I tested it with this script:

void main()
{
	CTimer Timer;
	Timer.start();
	Sleep(50);
	Timer.stop();
	Print("Stopped timer\n");

	CTimer@ timer_handle = @Timer;
	PrintElapsedTime(timer_handle);
	Print("Returned to main()\n");
}

void PrintElapsedTime(CTimer@ timer)
{
	Print("PrintElapsedTime() called\n");
	Print("Time elapsed: " + timer.milliseconds() + "\n");
}

3hoehEw.png

 

As you can see ReleaseRef() was called in PrintElapsedTime() for then handle passed in parameter

 

But this doesn't happen when you call a script function which takes in a handle as parameter from C++ application

Edited by Budskii

Share this post


Link to post
Share on other sites

Actually, script not calling ReleaseRef() might be an error from my part, doing some more testing, will update post

 

EDIT: it appears the script calls AddRef() and also ReleaseRef() when it is called from C++ that would explain why from my earlier test memory was never freed and so I thought ReleaseRef() wasn't called.

 

Create object in C++ (ref=1) -> call script function (ref += 1 -> ref = 2) -> finish script function (ref -=1 -> ref = 1)

 

I'd have to initliase the object with ref=0 from C++ and then that way it would delete in script, but it is supposed to be initliased to ref=1

Edited by Budskii

Share this post


Link to post
Share on other sites


They both work and script runs fine but I'm wondering if there is any different between the two?

 

There is no difference in this case. The compiler sees that the function expects a handle and thus implicitly adds the @ to argument. Whenever there is no doubt that a handle is desired, the compiler will do this for you so for the most part you will not have to type @ all the time.

 


I'd have to initliase the object with ref=0 from C++ and then that way it would delete in script, but it is supposed to be initliased to ref=1

 

Objects should be initialized with refcount = 1, to reflect that the one that creates the object holds a reference to the object.

 

When passing a newly created object to the script function you shouldn't increment the refcount further unless the application is also holding on to a reference to the object. 

 

By the way, how are you passing the handle to the script function? Depending on the method you use on the asIScriptContext to set the argument, the refcount will be automatically incremented for you.

 

asIScriptContext::SetArgAddress will not increment the refCount

asIScriptContext::SetArgObject will increment the refCount (if the script function expects a handle)

asIScriptContext::GetAddressOfArg will not increment the refCount

 

 

The script function will always call release on the handles it receives as parameters, the script doesn't know if the function is called from C++ or from another script function. You may see additional calls to addref/release depending on what the script does with the handle.

Share this post


Link to post
Share on other sites

Ah okay thanks. I was using SetArgObject(), that would explain the increment of ref counter. I've switched it to SetArgAddress and it works fine now

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!