Advertisement

Passing "this" As Argument ?&in

Started by July 22, 2016 03:47 PM
11 comments, last by WitchLord 8 years, 3 months ago

I noticed some weird behavior that I can't figure out. I have function that takes ?&in argument, and as soon as I pass "this" pointer there, it calls the destructor even if I don't do anything in a called function. What it seems to do is to actually create another instance of an object and that's the one that goes into the function, not the original handle. Is there something I don't get about using ?&in ?

class Foo

{

Foo() { print "Foo();\n"; }
~Foo() { print "~Foo();\n"; }

void bar() { print("start\n"); call(this); print("stop\n"); }

}

Foo f;

f.bar();

and the C++ function "call" is:

void Call(void* obj, int type_id)

{

std::cout << "call()" << std::endl;

}

engine->RegisterGlobalFunction("void call(?&in)", asFUNCTION(Call), asCALL_CDECL); assert( r >= 0 );

the result? after calling "call(this)" a new object is created, and destroyed as soon as the Call() function exits. So it actually prints this:

Foo()

start

Foo()

call()

~Foo()

stop

~Foo()

where that first ~Foo() is where new object is created. I guess that if I tried to modify object on C++ side, using that *obj pointer, it would be the object that is gone as soon as the function exits, not the one I think I'm modifying.

So the question is - should it make a "copy"? (I suppose that it actually does a copy of the object, because when I set some foo._value to "X" and default one was empty, the destructed object had it set to "X", indicating a copy rather than new object.

And how to prevent this copy? Actually it would be nice if I could decide if I want to pass a copy of an object vs. reference to an object in such case - is it possible with "?" notation, so it would work for any object?


Where are we and when are we and who are we?
How many people in how many places at how many times?

I've experienced this as well. Unlike handle parameters, ?& in will copy construct, since it isn't defined as a handle. it's like taking the object by reference: Foo& in. That will also copy construct.

To avoid this, explicitly convert the this pointer to a handle: @this. That will make Angelscript treat the argument as a handle, and will pass it properly.

Advertisement

Looks like "this" is actually an "object value" not "handle", so I tried passing @this and it seems to not create a copy.

What confused me there was the "&in" in argument declaration, which to me looks like a reference, and therefore it should pass by reference even if the object passed is not a "pointer"/"handle"? Like in C++ if I pass value object to a function taking the reference, it will implicitly pass it as reference, not as a copy.


Where are we and when are we and who are we?
How many people in how many places at how many times?

I've experienced this as well. Unlike handle parameters, ?& in will copy construct, since it isn't defined as a handle. it's like taking the object by reference: Foo& in. That will also copy construct.

To avoid this, explicitly convert the this pointer to a handle: @this. That will make Angelscript treat the argument as a handle, and will pass it properly.

Thanks! I managed to find out that @this thing a moment ago.

But what if I don't use "?" but declare specific object like MyClass& in - would that copy construct too? Doesn't it defeat the purpose of the reference passing? I must say that I'm using AS since 2011 and I'm still sometimes confused by it's handle/reference/value model :( What difference would be between func(MyClass) and func(MyClass&in)? Or does it only apply to "?&in" specific case?


Where are we and when are we and who are we?
How many people in how many places at how many times?

"& in" will always copy construct, with the exception of copy constructors and (i think) assignment operators. I believe it has to do with the engine's safe reference setting: http://www.angelcode.com/angelscript/sdk/docs/manual/angelscript_8h.html#a53c2e8a74ade77c928316396394ebe0f

I think that if you enable asEP_ALLOW_UNSAFE_REFERENCES, it will no longer copy construct them.

Ok, I think I get it now. I thought about it a bit and I wonder - with delayed execution, how do you handle possibility that when passed as argument to delayed function, a handle/reference can be invalid at the time of function execution? It would cause the script to crash probably? I thought about maybe enforcing only primitives or objects passed as weakref that won't hold on to object (this could cause object live forever with a delayed execution looped over, because there will be always argument waiting to be passed to a function, and if it does AddRef, then it will keep the object alive indefinitely?).

But then I have problems with weak_refs as they're not as easy to use as handle. I can't seem to pass weakref by value, only as weakref<>&in, can't pass it implicitly like func(myobject) for func(weakref<myobject>&in). There are no examples at all of using weakref as something passed to methods, and from quick prototyping it looks like it can't even find my function that has declaration "void weak_test(weakref<Player>& obj)":

desc: call_out: function not found 'void weak_test(weakref<Player>&in)'

and in the code:

void weak_test(weakref<Player>&in obj)
{
}
(and that works for anything else, so I suspect weakref somehow, or decl I try to find is wrong?)
PS. does anyone visit #angelscript @ FreeNode? Would be great to be able to chat with people knowing more about Angelscript than me, I'm constantly running into obstacles when trying some non-common things. Googling doesn't help much for these cases, and writing on the forum several times a day feels weird too. Would be great to make that channel a bit more alive and have way to chat with other AS'ers. I joined it and will look there from time to time in my daytime (European time) and sometimes at night.

Where are we and when are we and who are we?
How many people in how many places at how many times?
Advertisement

My scheduler class copies primitives and value types, and addrefs reference types. After the call finishes value types are destructed and reference types are released.

There should never be any object lifetime issues, but it does cost a bit more memory.

I've never used weakref myself, but i think it's intended to be used only as a local, global or member variable.

I've never been to FreeNode, but i am on GameSurge every now and then.

I hope someone who uses weakrefs could explain this class a bit, because either I'm doing something wrong or it's only intended to be saved as a member of an object and not pass around / return from functions like this:

weakref<Foo> function_returning_weakref()
{

return weakref<Foo>(this);

}

weakref<Foo> pFoo = function_returning_weakref();

This would be quite helpful, yet whatever I try to do I'm getting "No appropriate opAssign method found in 'weakref' for value assignment".


Where are we and when are we and who are we?
How many people in how many places at how many times?

PS. does anyone visit #angelscript @ FreeNode? Would be great to be able to chat with people knowing more about Angelscript than me, I'm constantly running into obstacles when trying some non-common things. Googling doesn't help much for these cases, and writing on the forum several times a day feels weird too. Would be great to make that channel a bit more alive and have way to chat with other AS'ers. I joined it and will look there from time to time in my daytime (European time) and sometimes at night.

Yep, I'm there every now and then. Haven't had my client on in a long time since I re-installed my OS, but I'll try to be on more.

'&in' is there to make it possible to guarantee the life time of the value that the reference refers to. AngelScript will make a copy of the value and store the copy on the local stack to be sure that it stays alive until the function returns. Without the local copy the object could potentially be destroyed while the function is being executed but before the function accesses the reference. In C++ it is the programmers responsibility to make sure the reference is always valid, but in AngelScript I don't put that burden on the programmer.

The weakref type currently doesn't have a copy constructor or assignment operator. That's why it doesn't allow you to pass this type by value. I'll have this implemented.

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