前面简述了HelloWorld程序的编写过程,使用到了GM的虚拟机gmMachine,下面我们将对GM进行一些简单的包装使得其适应到我们自己的项目中,使其可以很方便的执行脚本函数。
基本接口gmMachine::ExecuteString,我们要做的就是读取脚本文件的内容然后交给改接口去编译执行,同时我们需要进行一些错误处理。
GMScriptDrv为我包装的GameMonkey执行脚本文件的基础类,代码如下(GMScriptDrv.h):
#pragma once

#include "gmThread.h" // game monkey script

class GMScriptDrv

...{
public:
GMScriptDrv(void);
virtual ~GMScriptDrv(void);


/**//// Get the GM machine

gmMachine* GetMachine() ...{ return m_pGMMachine; }


/**//// 创建虚拟机,初始化
virtual void InitGM();


/**//// 释放资源
virtual void DestroyGM();

/**//// Update the virtual machine.
int Update(unsigned int deltaTime);


/**//// 加载并执行执行脚本文件
bool ExecuteFile(const char* fileName);


/**//// 运行一个脚本字符串,可以用来调用某个脚本语句
bool ExecuteString(const char* str);


/**//// 错误处理
/// 允许子类重载以不同的方式记录LOG
virtual void LogError(const char *a_str, ...);


/**//// Log any machine error messages that may be waiting
void LogAnyMachineErrorMessages();

private:
//! GM 虚拟机
gmMachine* m_pGMMachine;
};


1、InitGM(); 初试化,就是new一个gmMachine
2、Update(unsigned int deltaTime); 调用gmMachine::Execute函数,需要放在程序循环中调用
3、DestroyGM(); 销毁gmMachine实例,一般在退出程序时调用
4、ExecuteString(const char* str); 执行指定的字符串
bool GMScriptDrv::ExecuteString(const char* str)

...{
GM_ASSERT(m_pGMMachine);

int threadId = GM_INVALID_THREAD;
int errors = m_pGMMachine->ExecuteString(str, &threadId, true);
if (errors)

...{
LogAnyMachineErrorMessages();
}

return true;
}


5、ExecuteFile(const char* fileName); 加载并执行GM脚本文件,使用C API实现
bool GMScriptDrv::ExecuteFile(const char* fileName)

...{
FILE* scriptFile = NULL;
char* fileString = NULL;
int fileSize = 0;

GM_ASSERT(m_pGMMachine);

if( !(scriptFile = fopen(fileName, "rb")) )

...{
LogError("File Open Failed:%s.",fileName);
return false;
}

fseek(scriptFile, 0, SEEK_END);
fileSize = ftell(scriptFile);
fseek(scriptFile, 0, SEEK_SET);
fileString = new char [fileSize+1];
fread(fileString, fileSize, 1, scriptFile);
fileString[fileSize] = 0; // Terminating null
fclose(scriptFile);

//-- 执行字符串
ExecuteString(fileString);

delete [] fileString;
return true;
}


6、LogAnyMachineErrorMessages(); 错误处理,如果gmMachine::ExecuteString返回的不是0时就是执行字符串时出错啦,根据需要记录出错信息的LOG。
void GMScriptDrv::LogAnyMachineErrorMessages()

...{
bool first = true;
const char * message;
while((message = m_pGMMachine->GetLog().GetEntry(first)))

...{
LogError("%s", message);
}
m_pGMMachine->GetLog().Reset();
}


工作完成啦,可以开始使用我们的GM包装类啦。一切都是这么简单:
int main(int argc, char* argv[])

...{
int m_lastTime = timeGetTime();

GMScriptDrv gms;

// 初始化
gms.InitGM();

// todo something
gms.ExecuteFile("C://Hello.gm");

const char *myScript = "fruits = table ( "apple", "pear", "orange" ); "
"foreach ( frt in fruits ) { print(frt); } ";
gms.ExecuteString(myScript);

while(true)

...{
int curTime = timeGetTime();
int deltaTime = curTime - m_lastTime;
m_lastTime = curTime;

// Update GM 虚拟机
while (gms.Update(deltaTime))

...{
}
}

// 销毁退出
gms.DestroyGM(); return 0;
}


