一直想找一个跨平台的脚本,发现AngelScript简单易用,把我的实践分享给大家,希望能对关注AS的同学有所帮助。
我是用vc6编译的as2.2,把它编译成了一个静态库。
你看一下我的vc6工程中的注释就能明白as的用法。完整的vc6工程见附件,咦,怎么找不到如何上传附件啊。只好把我所有的代码贴在下面,但是你要自己到as的官网上下载他的源码,自己搭建环境了。这些代码也仅供参考一下了。
http://www.angelcode.com/angelscript/
// as_1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "angelscript.h"
#include "scriptstdstring/scriptstdstring.h"
#include "scriptbuilder/scriptbuilder.h"
using namespace std;
//回调函数,这个函数将收集as的错误信息,并输出到指定文件
void MessageCallback(const asSMessageInfo *msg, void *param)
{
const char *type = "ERR ";
if( msg->type == asMSGTYPE_WARNING )
type = "WARN";
else if( msg->type == asMSGTYPE_INFORMATION )
type = "INFO";
printf("%s (%d, %d) : %s : %s/n", msg->section, msg->row, msg->col, type, msg->message);
}
//例子,将要被注册的全局函数
void print(const string msg)
{
printf("%s", msg.c_str());
}
//例子,将要被注册的一个类
class CRef
{
public:
CRef();
virtual ~CRef();
void Addref();
void Release();
void print();
int refCount;
};
//
CRef::CRef()
{
// Let the constructor initialize the reference counter to 1
refCount = 1;
}
//
CRef::~CRef()
{
}
//这个方法需要实现,用于增加引用计数
void CRef::Addref()
{
// Increase the reference counter
refCount++;
}
//这个函数需要注册,用于减少引用计数
void CRef::Release()
{
// Decrease ref count and delete if it reaches 0
if( --refCount == 0 )
delete this;
}
//这个全局函数是生成CRef类的工厂函数
CRef *Ref_Factory()
{
// The class constructor is initializing the reference counter to 1
return new CRef();
}
//这个函数是一个方法的例子
void CRef::print()
{
printf("Hello~~~ world!/n");
}
int main(int argc, char* argv[])
{
//创建脚本引擎实例
asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
if (engine == NULL)
{
return 0;
}
//设置错误信息的回调函数
int r = engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);
if (r < 0)
{
engine->Release();
return 0;
}
// AngelScript 没有自己的字符串类型, 就像C++也没有自己的字符串类型一样。AngelScript 的SDK提供
// 了一些add on 的字符串类型,你可以选取一种,如下的函数选用std::string
RegisterStdString(engine);
//注册一个全局函数
r = engine->RegisterGlobalFunction("void print(const string msg)", asFUNCTION(print), asCALL_CDECL);
if (r < 0)
{
//注册失败
}
//注册一个类,在编写脚本时类的数据类型名称是"ref"
r = engine->RegisterObjectType("ref", 0, asOBJ_REF);
if (r < 0)
{
//注册失败
}
//注册这个类的工厂函数
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_FACTORY, "ref@ f()", asFUNCTION(Ref_Factory), asCALL_CDECL);
if (r < 0)
{
//注册失败
}
//注册这个类的引用计数函数
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_ADDREF, "void f()", asMETHOD(CRef,Addref), asCALL_THISCALL);
if (r < 0)
{
//注册失败
}
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASE, "void f()", asMETHOD(CRef,Release), asCALL_THISCALL);
if (r < 0)
{
//注册失败
}
//注册这个类的一个普通方法,甚至可以把一个全局函数注册成这个类的方法,这里并没有这样做
r = engine->RegisterObjectMethod("ref", "void print()", asMETHOD(CRef,print), asCALL_THISCALL);
if (r < 0)
{
//注册失败
}
//在这里,使用了as的另外一个插件,主要是用于加载一个脚本文件
CScriptBuilder builder;
//创建一个新模块
r = builder.StartNewModule(engine, "MyModule");
if( r < 0 )
{
printf("Unrecoverable error while starting a new module./n");
return 0;
}
//加载as脚本文件
r = builder.AddSectionFromFile("D://test//as_1//1.as");
if( r < 0 )
{
printf("Please correct the errors in the script and try again./n");
return 0;
}
//编译这个脚本文件,会进行语法检查,应该是把编译后的执行代码放到了内存中
r = builder.BuildModule();
if( r < 0 )
{
printf("Please correct the errors in the script and try again./n");
return 0;
}
//到MyModule中找到入口函数,这里是main()函数
asIScriptModule *mod = engine->GetModule("MyModule");
int funcId = mod->GetFunctionIdByDecl("void main()");
if( funcId < 0 )
{
printf("The script must have the function 'void main()'. Please add it and try again./n");
return 0;
}
//创建执行环境(上下文),
asIScriptContext *ctx = engine->CreateContext();
ctx->Prepare(funcId);//准备
r = ctx->Execute();//执行
if( r != asEXECUTION_FINISHED )
{
// The execution didn't complete as expected. Determine what happened.
if( r == asEXECUTION_EXCEPTION )
{
// An exception occurred, let the script writer know what happened so it can be corrected.
printf("An exception '%s' occurred. Please correct the code and try again./n", ctx->GetExceptionString());
}
}
//清理
ctx->Release();
engine->Release();
return 0;
}