天天看点

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;

}