一直想找一個跨平台的腳本,發現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, "[email protected] 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;
}