Jump to content

Simon Geilfus

Member Since 16 Feb 2014
Offline Last Active Feb 11 2015 05:13 AM

Posts I've Made

In Topic: Sending a pointer to a Primitive from a script to the application

18 December 2014 - 05:30 PM

Wouldn't this return an address pointing to the reference and not to the object itself?

It seems that if I print the void* ref from the variable parameter type function it gives me a different address than if I query directly the address using module->GetAddressOfGlobalVar( index );


I might be wrong but it looks like it's doing pretty much the same thing which is giving me a pointer that will not be valid as soon as we are out of the scope of the function. What I'm looking for is a pointer that can outlive that scope, so I can change the value later on.

In Topic: Casting value objects.

18 December 2014 - 03:09 PM

So here it is!

I have the same issue in several part of my code but this one is a good example because the base class is abstract and for this reason unregistrable as a value (because of not being instanciable).


// Source AddRef and Release Behaviors
std::map<geom::Source*, uint32_t> sSourceRefs;
void sourceAddRef( geom::Source* source )
    if( !sSourceRefs.count( source ) ){
    sSourceRefs[source] = 1;
    else sSourceRefs[source]++;
void sourceRelease( geom::Source* source )
if( sSourceRefs.count( source ) ){
    if( sSourceRefs[source] == 0 ){
    sSourceRefs.erase( sSourceRefs.find( source ) );
    //delete source;
// Conv to geom::Source
const geom::Source& sourceConv( const geom::Source& t ){ return t; }
void registerGeom( asIScriptEngine* engine )
    engine->SetDefaultNamespace( "geom" );
    // Source Type (the base class)
    engine->RegisterObjectType( "Source", sizeof(geom::Source), asOBJ_REF );
    // Source behaviors
    engine->RegisterObjectBehaviour( "Source", asBEHAVE_ADDREF, "void f()", asFUNCTION(sourceAddRef), asCALL_CDECL_OBJFIRST );
    engine->RegisterObjectBehaviour( "Source", asBEHAVE_RELEASE, "void f()", asFUNCTION(sourceRelease), asCALL_CDECL_OBJFIRST );
    // Cube Type (one of the derived classes)
    engine->RegisterObjectType( "Cube", sizeof(geom::Source), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK );
    // Cube behaviors
    Script::registerConstructor<geom::Cube>( engine, "Cube" );
    Script::registerDestructor<geom::Cube>( engine, "Cube" );
    Script::registerCopyConstructor<geom::Cube>( engine, "Cube" );
    Script::registerCopyAssignment<geom::Cube>( engine, "Cube" );
    engine->RegisterObjectMethod( "Cube", "const geom::Source& opImplConv() const", asFUNCTION( sourceConv ), asCALL_CDECL_OBJLAST );
                engine->SetDefaultNamespace"" );

So basically there is a series of geometric objects like geom::Cube, geom::Sphere, geom::Plane, etc... and all of them inherit from the base class geom::Source. The only reason to expose geom::Source is that a lot of other functions takes a const Source& as inputs. I'd love to be able to rely on some sort of polymorphism and not have to register the different functions several time for each type of geom classes.

In Topic: Casting value objects.

17 December 2014 - 06:10 AM

Thanks Andreas.


 opConv and opImplConv are intended to return a new value not a reference to the same value, so you wouldn't be using it for its intended purpose if you do this.


I thought opConv and opImplConv were a replacement for the depreciated value cast behavior. If we take the aswrapper test.cpp as an example, how would you replace the conversion code that starts at line 140? Would opConv and opImplConv be the way to go?



(though feel free to experiment)


It wouldn't solve your problem anyway, since the returned reference is to an object of unknown lifetime (at least as far as the compiler knows) and it will still need to make a copy of the object before giving it as a reference to the function.


Ok, I think I'm getting slowly the idea :)


So I did experiment a bit more with this. I tried to register an addRef and release behavior to my base class. Here's what I think is happening when the conversion happen. So basically I pass a Derived object to a function as a &in reference. When this happen and my opImplConv is executed, the addRef of the base class is called and the refcounting starts. Directly after the engine call the release function where I check if the pointer is correct and if the refcount is at zero I try to delete the object. I think at that point that the address is actually pointing to the actual Derived object and not a copy, which would explain why it crash if I delete the object when it's released... So if I'm getting it correctly, in this case it's not exactly a copy of the object but a reference. Is that right? 


Would that help if I post some code?


Thanks a lot anyway and sorry for being slow at understanding how this work!

In Topic: Casting value objects.

14 December 2014 - 02:34 PM

Great, thanks a lot for the explanation!


Last question though, does it means that giving a "const RefBase& opImplConv( )" to a Value type can potentially solve the whole "safe/copy" issue you are explaining above? 

In Topic: Casting value objects.

14 December 2014 - 01:10 PM

Alright, so I did some more tests and it seems that I managed to find a solution that works, but I was curious to still hear your opinion;


Would registering the base type as a asOBJ_REF | asOBJ_NOCOUNT with no factory or behaviors be something wrong?