GameMonkey脚本语言编程基础——函数绑定和函数调用

本文介绍了如何使用GameMonkey Script在C++与脚本语言间进行函数调用,包括C++调用脚本函数及脚本调用C++函数的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
Technorati 标签: GameMoney, 脚本语言

上篇中介绍了包装一个类来执行脚本文件,下面我们就要让我们的脚本更好的为我们工作,那就是使用函数交互调用。

1、c++中调用脚本函数;

首先需要新建一个.gm脚本文件,在脚本文件中编写一个函数代码,如下:

global sayHello = function()
{
    print( "Hello, World!");
};

幸运的是GM提供了方便的函数绑定和函数调用工具类,我们需要添加gmsrc/src目录中的所有c++文件到工程中,并且将该目录添加头文件引用目录。使用gmCall进行脚本函数的调用皆可。

void TestB(gmMachine* pMachince)
{
    gmCall call;
    if(call.BeginGlobalFunction(pMachince, "sayHello"))
    {
        call.End();
    }
}

从C++中调用脚本函数原始的方法就是使用gmFunctionObject类来进行,大致流程就是在gmMachine中索引到函数名称对应的函数指针,然后Push到gmThread中执行,更加详细的描述可以参考《Introduction to GameMonkey Script Part 2http://www.gamedev.net/reference/programming/features/gmscript2/page6.asp

int main()
{
    gmMachine gm;

    // Execute a simple script file
    gmLoadAndExecuteScript ( &gm, "scripts/function_test.gm" );

    gmVariable funcName, funcFound;
    funcName.SetString( gm.AllocStringObject("sayHello") );
    // find in global table
    funcFound = gm.GetGlobals()->Get(funcName);

    if ( funcFound.m_type != GM_FUNCTION )
    {
        std::cout << "Failed to find 'sayHello'";
        return 0;
    }
    // Get function object from variable
    gmFunctionObject *func = (gmFunctionObject *)funcFound.m_value.m_ref;
    gmThread *thread = gm.CreateThread();
    // Push empty 'this' value
    thread->Push( gmVariable::s_null );
    thread->PushFunction( func );
    // No params needed
    // Get a blank variable to grab the return
    gmVariable returnVar;
    // execute the thread
    int state = thread->PushStackFrame( 0 );
    if (state != gmThread::KILLED )
    {
        state = thread->Sys_Execute( &returnVar );
    }

    return 0;
}

2、脚本中调用c++函数。

脚本调用c++函数稍复杂一点就是需要将预先提供GM_CDECL函数原型和实现的c++代码,然后使用gmFunctionEntry将函数注册到GM虚拟机中,才能在脚本中调用对应的c++版本函数。还是来看代码:

// C++ GM_CDECL 函数
int GM_CDECL gm_Add(gmThread* a_thread)
{
    GM_CHECK_NUM_PARAMS(2);
    GM_CHECK_INT_PARAM(x, 0);
    GM_CHECK_INT_PARAM(y, 1);

    a_thread->PushInt( x+y );
    return GM_OK;
}

/**
* 注册C++函数绑定
*/
void TestRegisterScriptBindings(gmMachine* pMachince)
{
    // 需要绑定的函数table
    static gmFunctionEntry MathFunBinds[] =
    {
        /*gm
        /lib Math
        /brief Add
        */
        {"Add", gm_Add},
    };
    // 注册函数到虚拟机中
    GM_ASSERT(pMachince!=NULL);
    pMachince->RegisterLibrary(MathFunBinds, sizeof(MathFunBinds) / sizeof(MathFunBinds[0]), "Math");
}

这样就成功的将一个c++函数注册到了GM的虚拟机中,其库名称为Math,当然可可以不填写库名称,库名称将在后面的介绍类的绑定和namespace的绑定中发挥不可替代的作用,不用再像LUA那样担心命名的污染。接下来我们需要在脚本中调用Math.Add函数啦。首先在.gm脚本中新建一个脚本函数,代码如下:

global myAdd = function( a_x, a_y )
{
    res = Math.Add(a_x, a_y);   
    print("Add Result: ", res );
    return res;
};

编写测试代码检测调用的结果,还是来看代码:

void TestA(gmMachine* pMachince)
{
    // 调用脚本函数
    gmCall call;
    if(call.BeginGlobalFunction(pMachince, "myAdd"))
    {
        // 传递脚本函数参数
        call.AddParamInt( 10 );
        call.AddParamInt( 2 );

        call.End();

        // 处理返回值
        int myReturn = 0;
        if (call.GetReturnedInt( myReturn ) )
        {
            std::cout << "myAdd returned " << myReturn << std::endl;
        }
        else
        {
            std::cout << "myAdd returned an incorrect value" << std::endl;
        }
    }
}

输出结果:

Add Result: 12

myAdd returned 12

看起来还是有些复杂的,GM没有提供C++函数的自动绑定工具,也没有提供任何函数库的绑定,如果需要脚本函数调用C++ API或者其他函数库则需要费一番功夫,GameMonkey网站上提供将提供More bindings for useful tools and applications。但愿GM能早日有像LUAPlus一样强大的bind工具。

作者:吴紫鄂(zewu@live.cn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值