天天看點

AngelScript實踐

一直想找一個跨平台的腳本,發現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;

}