🎉 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!

Calling a method on a script class from C++

Started by
2 comments, last by WitchLord 9 years, 8 months ago

Given the following script code:


class Foo
{
    void test()
    {
        print("hello");
    }
}

Foo foo;

If given the strings "foo" and "test", I'm trying to programmatically execute foo.test(); The instructions here are straightforward, except that they assume that you have a asIObjectType and that's what I'm getting stuck on.



asIScriptFunction* GetScriptMethodToExecute(void*& objAddressOut)
{
    int varIdx = scriptModule.GetGlobalVarIndexByName("foo");
    if ( varIdx == asNO_GLOBAL_VAR )
        varIdx = scriptModule.GetGlobalVarIndexByDecl("foo");
    if ( varIdx < 0 )
        return NULL;

    objAddressOut = scriptModule.GetAddressOfGlobalVar(varIdx);

    // Here's where the trouble starts.. I need an asIObjectType*


    // try 1
    {
        int typeId = 0;
        scriptModule.GetGlobalVar(varIdx, NULL, NULL, &typeId, NULL);

        // this returns NULL (though typeId seems OK)
        asIObjectType* pType = scriptModule.GetObjectTypeByIndex(typeId);
    }

    // try 2
    {
        // this returns NULL
        asIObjectType* pType = scriptModule.GetObjectTypeByIndex(varIdx);
    }

    // try 3
    {
        // Note: it looks like this is returning "Foo ::foo". Should the space be in there?
        const char* varDecl = scriptModule.GetGlobalVarDeclaration(varIdx, true);

        // this returns NULL
        asIObjectType* pType = scriptModule.GetObjectTypeByDecl(varDecl);
    }

    // try 4
    {
        // this returns NULL
        asIObjectType* pType = scriptModule.GetObjectTypeByDecl("Foo::foo");
    }

    // try 5
    {
        // this works!
        asIObjectType* pType = scriptModule.GetObjectTypeByDecl("Foo");
    }

    // try 6
    {
        // Note: this returns "Foo foo"
        const char* varDecl = scriptModule.GetGlobalVarDeclaration(varIdx, false);

        // this returns NULL
        asIObjectType* pType = scriptModule.GetObjectTypeByDecl(varDecl);
    }


    asIScriptFunction* pScriptFunc = pType->GetMethodByName("test");
    if ( NULL == pScriptFunc )
    {
        pScriptFunc = pType->GetMethodByDecl("test");
    }

    return pScriptFunc;
}

Given the above script and "foo" and "test", how can I get the variable type's asIObjectType* most directly?

Thank you!

Advertisement

Looks like given a typeId, I needed to call:


asIObjectType* pType = scriptEngine.GetObjectTypeById(typeId);

I was looking for this function the first time around, but didn't locate it.

Now that I got the above working (would still appreciate your feedback as to whether that's the optimal approach), I ran into one counterintuitive behavior related to namespaces.

Try 1:


namespace ns
{
   class foo
   {
        void test() {}
   }
}

ns::foo bar;

As expected, I can give my code the strings "bar" and "test" and it calls bar.test() correctly.

Try 2:


class foo()
{
    void test() {}
}

namespace ns
{
    foo bar;
}

"bar" and "test" no longer works.

"ns::bar" and "test" doesn't work.

"ns::foo bar" and "test" doesn't work.

"ns::foo ns::bar" and "test" work.

From a usability perspective, I would never think to provide "ns::foo and ns::bar" as the variable's declaration. The declaration of foo isn't in the namespace, so why doesn't "foo ns::bar" work? or just "ns::bar" ?

Thank you.

Probably the easiest way of getting the global variable 'bar' in the last example is this way:

mod->SetDefaultNamespace("ns");
int idx = mod->GetGlobalVarIndexByName("bar");
 
// or
mod->SetDefaultNamespace("ns");
idx = mod->GetGlobalVarIndexByDecl("foo bar");

Of course, this assumes you know in which namespace the variable is declared in.

Without calling SetDefaultNamespace first, it is only possible to get the variable index with:

int idx = mod->GetGlobalIndexByDecl("foo ns::bar");

"ns::foo ns::bar" gives the same result, and works because foo is declared in the parent namespace of 'ns' (in this case the global namespace).

GetGlobalVarIndexByName doesn't support "ns::bar" because it only expects an identifier with the name of the wanted variable.

If you don't know the namespace, you can manually iterate over all global variables with GetGlobalVarCount, and GetGlobalVar until you find the one that matches.

To get the object type of the variable you should use engine->GetObjectTypeById() as you already discovered.

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