🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Virtual class registration problems?

Started by
3 comments, last by ALRAZ 16 years, 3 months ago
Hello I'm using the co-routines example to do a little testing with AngelScript. I'm Using Code::Blocks + MinGW to compile. I'll try to explain my problem as clear as possible... Basically, the script returns with code 3 (asEXECUTION_EXCEPTION) as soon as i try to run any mothod of an instantiated object. Here is what i have: First of all, there is a small virtual class which is supposed to handle input:

class ygi_input
{
public:
    virtual ~ygi_input () {};

    virtual void clear () = 0;
    virtual bool load (const string FileName, const string Player, const string Name, const string Default = "") = 0;
    virtual bool save (const string FileName) = 0;


    /*
    some other methods... 
    */

    virtual bool waspressed  (const sint32 FramesBack) = 0;
    virtual bool wasreleased (const sint32 FramesBack) = 0;
    virtual sint32 value () = 0;
};
there is an inherited class which implements all the virtual functions from this base class, but the application only uses the main class via pointers... somthing like:

ygi_input MyInput = CreateInputClass ();


ygi_input *CreateInputClass ()
{
//DerivedClass is something like DerivedClass : public ygi_input
DerivedClass *Cls = new DerivedClass;

   return (ygi_input *) Cls;
}
So, what i did is use the Coroutines example which comes with AngilScript and alther it a little bit to include handling of this input class. First, i created some basic functions for behaviour and some others for testing...

map <ygi_input *, int> RefCounter;


ygi_input *InputFactory ()
{
    ygi_input *Ret = ygi_createinput ();

    if (Ret != NULL)
        RefCounter [Ret] = 1;

    return Ret;
}

void InputAddRef (ygi_input *Obj)
{
    RefCounter [Obj] ++;
}

void InputRemRef (ygi_input *Obj)
{
    RefCounter [Obj] --;
    if (RefCounter [Obj] == 0)
    {
        ygi_releaseinput (Obj);
    }
}

bool InputLoad (ygi_input *Obj, string A, string B, string C, string D)
{
    return Obj->load (A, B, C, D);
}

bool InputPressed (ygi_input *Obj, sint32 Frms)
{
    return Obj->waspressed (Frms);
}

void InputClear (ygi_input *Obj)
{
    Obj->clear ();
}
And altered the ConfigureEngine function a little bit to add the object to the script:

   // [...]

   RegisterScriptAny(engine);

	r = engine->RegisterObjectType("ygi_input", sizeof(ygi_input), asOBJ_REF); assert( r >= 0 );

	r = engine->RegisterObjectBehaviour("ygi_input", asBEHAVE_FACTORY, "ygi_input @f()", asFUNCTION(InputFactory), asCALL_GENERIC); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("ygi_input", asBEHAVE_ADDREF,  "void f()",       asFUNCTION(InputAddRef),  asCALL_GENERIC); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("ygi_input", asBEHAVE_RELEASE, "void f()",       asFUNCTION(InputRemRef),  asCALL_GENERIC); assert( r >= 0 );

    r = engine->RegisterObjectMethod("ygi_input", "bool load (string ∈, string ∈, string ∈, string ∈)", asFUNCTION(InputLoad), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
    r = engine->RegisterObjectMethod("ygi_input", "bool waspressed  (const int)", asMETHODPR(ygi_input, waspressed, (const sint32), bool), asCALL_THISCALL); assert( r >= 0 );*/
    r = engine->RegisterObjectMethod("ygi_input", "void clear ()", asFUNCTION(InputClear), asCALL_GENERIC); assert( r >= 0 );

   // [...]
I can create object of type "ygi_input" in the scripts, but, as soon as y try to call any of the methods clear, load or waspressed, the (*currentCtx)->Execute() function returns with code 3, which the .h file says is asEXECUTION_EXCEPTION. I tried with many different ways to register the method but all of them took me to the same problem :( Any ideas or help...?
format c: /q
Advertisement
oh, i forgot...
here are some examples of other ways i tried to register the clear () method, none of which worked:

r = engine->RegisterObjectMethod("ygi_input", "void clear ()", asMETHOD (ygi_input, clear), asCALL_THISCALL);r = engine->RegisterObjectMethod("ygi_input", "void clear ()", asMETHODPR (ygi_input, clear, (), void), asCALL_THISCALL);r = engine->RegisterObjectMethod("ygi_input", "void clear ()", asFUNCTION(InputClear), asCALL_CDECL_OBJFIRST);


i also tried with asFUNCTION and asCALL_CDECL and asCALL_STDCALL but they gave an "invalid configuration" error while building the script.

[Edited by - ALRAZ on March 9, 2008 7:15:28 PM]
format c: /q
hi

i use pre-factory version of AS (2.10) so i don't exactly know how it works, but it seems that calling convention of InputFactory, InputAddRef, InputRemRef does not match. You are registering them as asCALL_GENERIC while they are ordinary asCALL_CDECL (assuming cdecl is default calling convention here)

generic functions should look like:
void __cdecl func(asIScriptGeneric *gen);

so i suspect that AS ignores pointer that is returned in factory function (because it's not gen->SetReturnObject(Ret) way) and all consecutive calls to this oblect results in calling methods on null pointer, which gives that exception

same goes for InputClear, this one should work as asCALL_CDECL_OBJFIRST/LAST

last thing i've noticed is registering InputClear function with 'string' arguments as passed by reference while fuction expects them by value
ok, i think i got it, but...
shouldn't it work this way?

r = engine->RegisterObjectMethod("ygi_input", "void clear ()", asMETHOD (ygi_input, clear), asCALL_THISCALL);
format c: /q
nevermind my last post... was stupid enought, i know... sorry, im very newbie to this "calling convention" stuff.

Anyways, i did some try and error and found out how to make it work, thank you so much Behc, since this was mostly becouse of your post.

so, what i did was change the factory, add ref and remove more or less as you told me:

        r = engine->RegisterObjectBehaviour("ygi_input", asBEHAVE_FACTORY, "ygi_input @f()", asFUNCTION(InputFactory), asCALL_CDECL); assert( r >= 0 );	r = engine->RegisterObjectBehaviour("ygi_input", asBEHAVE_ADDREF,  "void f()",       asFUNCTION(InputAddRef),  asCALL_CDECL_OBJFIRST); assert( r >= 0 );	r = engine->RegisterObjectBehaviour("ygi_input", asBEHAVE_RELEASE, "void f()",       asFUNCTION(InputRemRef),  asCALL_CDECL_OBJFIRST); assert( r >= 0 );


also, ignored all other functions except for "clear", and then was able to register it via asMETHODPR and everything seems to be working very nicely now :)

thanks again

[Edited by - ALRAZ on March 10, 2008 5:08:53 PM]
format c: /q

This topic is closed to new replies.

Advertisement