AngelScript works in debug mode but not in release

Started by
1 comment, last by howie_007 9 years, 7 months ago

I recently added AngelScript (2.29.1 WIP) to my engine. After getting it working and setting up some types and a few scripts, I then rebuilt everything in release mode to discover it wasn't working. I'm building the source files into static libraries using the provided VC10 project files.

Also the MessageCallback is not being called to display any error info. With some testing I noticed registering my objects and global functions compile in release mode but if they are used in a script, there will be a build error with no error info.

Below is the value type I made. It's my color class holding 4 floats and a bunch of overloaded operators.



/************************************************************************
*    FILE NAME:       scriptcolor.cpp
*
*    DESCRIPTION:     CColor script object registration
************************************************************************/

// Physical component dependency
#include <script/scriptcolor.h>

// Standard lib dependencies
#include <assert.h>

// AngelScript lib dependencies
#include <angelscript.h>

// Game lib dependencies
#include <common/color.h>

namespace NScriptColor
{
    /************************************************************************
	*    desc:  Constructor
	************************************************************************/
    static void Constructor(void * thisPointer)
    {
	    new(thisPointer) CColor();
    }

    /************************************************************************
	*    desc:  Copy Constructor
	************************************************************************/
    static void CopyConstructor(const CColor & other, void * pThisPointer)
    {
	    new(pThisPointer) CColor(other);
    }

    static void ConstructorFromFloats(float r, float g, float b, float a, void * pThisPointer)
    {
	    new(pThisPointer) CColor(r, g, b, a);
    }

    /************************************************************************
	*    desc:  Destructor
	************************************************************************/
    static void Destructor(void * pThisPointer)
    {
	    ((CColor*)pThisPointer)->~CColor();
    }


    /************************************************************************
	*    desc:  Register the type
	************************************************************************/
    void Register( asIScriptEngine * pEngine )
    {
        // Register type
        assert( pEngine->RegisterObjectType("CColor", sizeof(CColor), asOBJ_VALUE | asOBJ_APP_CLASS | asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR ) > -1 );

        // Register the object operator overloads
	    assert( pEngine->RegisterObjectBehaviour("CColor", asBEHAVE_CONSTRUCT, "void f()",                  asFUNCTION(Constructor), asCALL_CDECL_OBJLAST) > -1 );
	    assert( pEngine->RegisterObjectBehaviour("CColor", asBEHAVE_CONSTRUCT, "void f(const CColor & in)", asFUNCTION(CopyConstructor), asCALL_CDECL_OBJLAST) > -1 );
	    assert( pEngine->RegisterObjectBehaviour("CColor", asBEHAVE_CONSTRUCT, "void f(float, float, float, float)", asFUNCTION(ConstructorFromFloats), asCALL_CDECL_OBJLAST) > -1 );
	    assert( pEngine->RegisterObjectBehaviour("CColor", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destructor), asCALL_CDECL_OBJLAST) > -1 );

        // assignment operator
        assert( pEngine->RegisterObjectMethod("CColor", "CColor & opAssign(const CColor & in)", asMETHODPR(CColor, operator =, (const CColor &), CColor &), asCALL_THISCALL) > -1 );

        // binary operators
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opAdd ( const CColor & in )", asMETHODPR(CColor, operator +, (const CColor &) const, CColor), asCALL_THISCALL) > -1 );
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opSub ( const CColor & in )", asMETHODPR(CColor, operator -, (const CColor &) const, CColor), asCALL_THISCALL) > -1 );
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opMul ( const CColor & in )", asMETHODPR(CColor, operator *, (const CColor &) const, CColor), asCALL_THISCALL) > -1 );
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opDiv ( const CColor & in )", asMETHODPR(CColor, operator /, (const CColor &) const, CColor), asCALL_THISCALL) > -1 );

        assert( pEngine->RegisterObjectMethod("CColor", "CColor opAdd ( float )", asMETHODPR(CColor, operator +, (float) const, CColor), asCALL_THISCALL) > -1 );
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opSub ( float )", asMETHODPR(CColor, operator -, (float) const, CColor), asCALL_THISCALL) > -1 );
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opMul ( float )", asMETHODPR(CColor, operator *, (float) const, CColor), asCALL_THISCALL) > -1 );
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opDiv ( float )", asMETHODPR(CColor, operator /, (float) const, CColor), asCALL_THISCALL) > -1 );

        // compound assignment operators
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opAddAssign ( const CColor & in )", asMETHODPR(CColor, operator +=, (const CColor &), CColor), asCALL_THISCALL) > -1 );
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opSubAssign ( const CColor & in )", asMETHODPR(CColor, operator -=, (const CColor &), CColor), asCALL_THISCALL) > -1 );
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opMulAssign ( const CColor & in )", asMETHODPR(CColor, operator *=, (const CColor &), CColor), asCALL_THISCALL) > -1 );
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opDivAssign ( const CColor & in )", asMETHODPR(CColor, operator /=, (const CColor &), CColor), asCALL_THISCALL) > -1 );

        assert( pEngine->RegisterObjectMethod("CColor", "CColor opAddAssign ( float )", asMETHODPR(CColor, operator +=, (float), CColor), asCALL_THISCALL) > -1 );
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opSubAssign ( float )", asMETHODPR(CColor, operator -=, (float), CColor), asCALL_THISCALL) > -1 );
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opMulAssign ( float )", asMETHODPR(CColor, operator *=, (float), CColor), asCALL_THISCALL) > -1 );
        assert( pEngine->RegisterObjectMethod("CColor", "CColor opDivAssign ( float )", asMETHODPR(CColor, operator /=, (float), CColor), asCALL_THISCALL) > -1 );

        // Class members
        assert( pEngine->RegisterObjectMethod("CColor", "void Set( float r, float g, float b, float a )", asMETHOD(CColor, Set), asCALL_THISCALL) > -1 );

        // Register property
        assert( pEngine->RegisterObjectProperty("CColor", "float r", asOFFSET(CColor, r)) > -1 );
	    assert( pEngine->RegisterObjectProperty("CColor", "float g", asOFFSET(CColor, g)) > -1 );
	    assert( pEngine->RegisterObjectProperty("CColor", "float b", asOFFSET(CColor, b)) > -1 );
	    assert( pEngine->RegisterObjectProperty("CColor", "float a", asOFFSET(CColor, a)) > -1 );
    }

}   // NScriptColor

This is my script class I'm using to pass in as a reference. This is how my scripts will affect my sprite class's behavior.


/************************************************************************
*    desc:  Register the class with AngelScript
************************************************************************/
void CScriptComponent2d::Register( asIScriptEngine * pEngine )
{
    // Register CScriptComponent2d reference and methods
    assert( pEngine->RegisterObjectType("CScriptComponent2d", 0, asOBJ_REF|asOBJ_NOCOUNT) > -1 );
    assert( pEngine->RegisterObjectMethod("CScriptComponent2d", "void SetVisible(bool visible)", asMETHOD(CScriptComponent2d, SetVisible), asCALL_THISCALL) > -1 );
    assert( pEngine->RegisterObjectMethod("CScriptComponent2d", "void SetColor(CColor & in)", asMETHOD(CScriptComponent2d, SetColor), asCALL_THISCALL) > -1 );
    assert( pEngine->RegisterObjectMethod("CScriptComponent2d", "const CColor & GetColor()", asMETHOD(CScriptComponent2d, GetColor), asCALL_THISCALL) > -1 );
    assert( pEngine->RegisterObjectMethod("CScriptComponent2d", "const CColor & GetDefaultColor()", asMETHOD(CScriptComponent2d, GetDefaultColor), asCALL_THISCALL) > -1 );
    assert( pEngine->RegisterObjectMethod("CScriptComponent2d", "uint GetFrameCount()", asMETHOD(CScriptComponent2d, GetFrameCount), asCALL_THISCALL) > -1 );
    assert( pEngine->RegisterObjectMethod("CScriptComponent2d", "void SetFrame(uint index)", asMETHOD(CScriptComponent2d, SetFrame), asCALL_THISCALL) > -1 );

}   // Register

Here's my Global functions. Nothing too fancy. Just the bare basics.


/************************************************************************
*    FILE NAME:       scriptglobals.cpp
*
*    DESCRIPTION:     AngelScript global function registration
************************************************************************/

// Physical component dependency
#include <script/scriptglobals.h>

// Standard lib dependencies
#include <assert.h>

// AngelScript lib dependencies
#include <angelscript.h>

// Game lib dependencies
#include <utilities/highresolutiontimer.h>
#include <utilities/genfunc.h>

namespace NScriptGlobals
{
    /************************************************************************
    *    desc:  Suspend the script to the game loop                                                             
    ************************************************************************/
    void Suspend()
    {
        asIScriptContext *ctx = asGetActiveContext();

        // Suspend the context so the game loop can resumed
        if( ctx )
            ctx->Suspend();

    }   // Suspend


    /************************************************************************
	*    desc:  Register the global functions
	************************************************************************/
    void Register( asIScriptEngine * pEngine )
    {
        assert( pEngine->RegisterGlobalFunction("float GetElapsedTime()", asMETHOD(CHighResTimer, GetElapsedTime), asCALL_THISCALL_ASGLOBAL, &CHighResTimer::Instance()) > -1 );
        assert( pEngine->RegisterGlobalFunction("void Print(string &in)", asFUNCTION(NGenFunc::PostDebugMsg), asCALL_CDECL) > -1 );
        assert( pEngine->RegisterGlobalFunction("void Suspend()", asFUNCTION(Suspend), asCALL_CDECL) > -1 );
    }

}   // NScriptGlobals

Here's my test script.


void Fade( CScriptComponent2d @script )
{
    Hold( 500 );

    while( true )
    {
        Hold( 100 );

        ColorTo( 1000, CColor(1,1,1,0), script );

        Hold( 200 );

        ColorTo( 1000, CColor(1,1,1,1), script );
    }
}

void Animate( CScriptComponent2d @script )
{
    while( true )
    {
        Play( 24, script );
    }
}

And here's my utilities script that I'm building as a script library of general purpose functions.


/************************************************************************
*    FILE NAME:       utilities.ang
*
*    DESCRIPTION:     General purpose utility scripts
************************************************************************/

/************************************************************************
*    desc:  Color to the final color in time                                                             
************************************************************************/
void ColorTo( float time, CColor final, CScriptComponent2d & script )
{
    CColor current = script.GetColor();
    CColor inc = (final - script.GetColor()) / time;

    while( true )
    {
        time -= GetElapsedTime();

        current += inc * GetElapsedTime();
        script.SetColor( current );

        if( time < 0 )
        {
            script.SetColor( final );
            break;
        }

        Suspend();
    }

}   // ColorTo


/************************************************************************
*    desc:  Play the animation                                                             
************************************************************************/
void Play( float fps, CScriptComponent2d & script )
{
    float time = 1000.0 / fps;
    uint frameCount = script.GetFrameCount();

    for( uint i = 0; i < frameCount; ++i )
    {
        script.SetFrame( i );

        Hold( time );
    }

}   // ColorTo


/************************************************************************
*    desc:  Hold the script execution in time                                                            
************************************************************************/
void Hold( float time )
{
    while( true )
    {
        time -= GetElapsedTime();

        if( time < 0 )
            break;

        Suspend();
    }

}   // Hold

As stated above, everything works in debug mode and the only thing that works in release mode is an empty do nothing function. Even that won't work if I add the global function Print("test");

AngelScript is so amazing.

Thanks for your help!

Advertisement

If you're not using a custom assert(), then lines like


assert( pEngine->RegisterObjectType("CScriptComponent2d", 0, asOBJ_REF|asOBJ_NOCOUNT) > -1 );

Turn into something like this in release:


(void)0;

Asserts are intended to only be run in debug code.

I suggest rewriting your lines like this:


{ int r= pEngine->RegisterObjectType("CScriptComponent2d", 0, asOBJ_REF|asOBJ_NOCOUNT); assert(r > -1 ); }

OMG... I totally forgot about that and got caught up in making the code a bit more compact. Thank you so much Reaper.

This topic is closed to new replies.

Advertisement