goo blog サービス終了のお知らせ 

gooブログはじめました!

写真付きで日記や趣味を書くならgooブログ

DxLibの関数をangelscriptから呼ぶ

2010-04-11 16:58:26 | インポート

DxLibの関数を登録

DxLibの関数をよぶangelscript

<form>

DxLibの関数を登録

DxLibの描画用関数をグローバル関数として宣言してその関数をanglescriptに登録して、呼び出せるようにする。 当然引数の型、数はDxLibの関数と同じにする。 

描画用に下記の関数を登録する。
DrawLine() 
DrawBox()   
DrawCircle()
DrawOval()   
DrawTriangle()
DrawPixel()


グローバル関数はDxLibの関数とわかるようにする。DxLibの関数にmyをつけただけ。 //retutn int 
int myDrawLine( int x1 , int y1 , int x2 , int y2 ,int Color ) 
{
int iRet = DrawLine( x1, y1, x2, y2, Color );
return iRet;
}

<textarea rows="8" cols="75" readonly="readonly">#include "CAngelScriptMgr.h" #include "CMoveObject.h" //#include <windows.h> // timeGetTime() #include "LogUtility.h" #define OK 0 #define NG -1 //angelscript,c++両方で使用できるグローバル変数を定義する float g_fdata = 0; float g_fx = 0; float g_fy = 0; int gg_itimer = 0; int g_LogLevel = LOG_WARN; //scriptひとつひとつ読み込み、ビルドに成功した場合bsuccessをtrueに設定しておく struct _ScriptList { char *scriptname; //angel script名 bool bsuccess; //scrptnameのangelscriptがビルドできたか }ScriptList[] = { { "resource/script/test11.as", false }, { "resource/script/test12.as",false }, { "resource/script/test13.as",false }, { "resource/script/dxlib_img_bgm_handle.as",false }, }; #define ANGEL_SCRIPT_NUM (sizeof(ScriptList)/sizeof(ScriptList[0]) ) //angle scritptないで使用するmethodがふえたらここに追加 //別々のscript(ファイル)にある関数でもここにはすべて記述する。 chDescriptionにはどのファイル名で定義してあるかも記述しておく //asIScriptContextのmethodでangelscriptから戻り値を受け取ることができるのは以下の型のみ //chFuncIDは戻り値の型が違う場合c++側で再コンパイルが必要 //GetReturnAddress(),GetReturnByte(),GetReturnDouble() //GetReturnDWord(),GetReturnFloat(),GetReturnObject() //GetReturnQWord(),GetReturnWord() //test13.asにはDxLibの関数をangelscriptから使用できるようにする。 //test11.asはテスト用 struct _AngelFuncList { int iID; //index、for,while 用途 char *chFuncID; //angle scriptのasIScriptContext->Prepare(funcId); のfuncIdに指定する文字列 char *chDescription; //angle script用の関数説明用 }AngelFuncList[] = { {0,"float test1()","print test file:test11.as"}, {1,"CMoveObject getscriptreturn()"," file:test11.as"}, {2,"CMoveObject getscriptreturn2( CMoveObject cmove )"," file:test11.as"}, {3,"void DxLibFuncTest()"," file:test13.as"}, {4,"int DrawLine_Test()"," file:test13.as"}, {5,"int DrawBox_Test()"," file:test13.as"}, {6,"int DrawCircle_Test()"," file:test13.as"}, {7,"int DrawOval_Test()"," file:test13.as"}, {8,"int DrawTriangle_Test()"," file:test13.as"}, {9,"int DrawPixel_Test()"," file:test13.as"}, {80,"int xupdate( CMoveObject &out cmove )"," file:test13.as"}, {100,"void SetGlobalArrayLength( uint itype, uint ilength )"," file:dxlib_img_bgm_handle.as"}, {101,"void SetHandle( uint itype, uint index, uint ihandle )"," file:dxlib_img_bgm_handle.as"}, {15,"float test2()"," file:test2.as"}, {16,"float TestCorutine()","corotine test file::test3.as"}, //{3,"int test4()",""}, }; //anglesciprtで使用する関数の数 #define ANGEL_FUNC_NUM  (sizeof(AngelFuncList)/sizeof(AngelFuncList[0]) ) //scriptarray test asIScriptArray *floatArray = 0; asIScriptArray *stringArray = 0; //このクラスのコンストラクタで、angelscriptの関数類を使えるようにしておく CAngelScriptMgr::CAngelScriptMgr() : m_pasengine( NULL ),m_pasmod( NULL ),m_pasctx( NULL ), m_pcontextMgr( NULL ), m_dwTimeOut( 1000 ) { int iRet = OK; m_mapAngelfunc.clear(); //angelscriptのengine初期化 iRet = InitializeAngelEngine(); assert( iRet >= 0 ); //c++,angelscript両方で使用する変数登録 iRet = RegisterProperty(); assert( iRet >= 0 ); //angelscriptで使用したいc++のクラスを登録 iRet = RegisterMyClass(); assert( iRet >= 0 ); //angelscriptをひとつひとつ読み込みビルドできるかcheck iRet = CheckBuild(); assert( iRet >= 0 ); SetAngelFuncMap(); } CAngelScriptMgr::~CAngelScriptMgr() { if( m_pasctx != NULL ) { m_pasctx->Release(); } if( m_pasengine != NULL ) { m_pasengine->Release(); } if( m_pcontextMgr != NULL ) { delete  m_pcontextMgr; m_pcontextMgr = NULL; } if( m_pasmod != NULL ) { m_pasmod = NULL; } m_mapAngelfunc.clear(); } void CAngelScriptMgr::CommonErrorMsg() { int ifuncid = m_pasctx->GetExceptionFunction(); asIScriptFunction *func = m_pasengine->GetFunctionDescriptorById( ifuncid ); cout << "func: " << func->GetDeclaration() << endl; cout << "modl: " << func->GetModuleName() << endl; cout << "sect: " << func->GetScriptSectionName() << endl; cout << "line: " << m_pasctx->GetExceptionLineNumber() << endl; cout << "desc: " << m_pasctx->GetExceptionString() << endl; PUT_LOG( g_LogLevel,"func:%s\n",func->GetDeclaration() ); PUT_LOG( g_LogLevel,"modl:%s\n", func->GetModuleName() ); PUT_LOG( g_LogLevel,"sect:%s\n", func->GetScriptSectionName() ); PUT_LOG( g_LogLevel,"line:%d\n", m_pasctx->GetExceptionLineNumber() ); PUT_LOG( g_LogLevel,"line:%d\n", m_pasctx->GetExceptionString() ); func->Release(); } void CAngelScriptMgr::DisplayErrorMsg( int err ) { int ifuncid = m_pasctx->GetExceptionFunction(); asIScriptFunction *func = m_pasengine->GetFunctionDescriptorById( ifuncid ); //エラー内容によってメッセージを分ける。coutはコマンドライン用、PUT_LOGはOutputDebugPrintを使い //どちらでもメッセージが出力されるようにする switch( err ) { case asEXECUTION_ABORTED: cout << "The script was aborted before it could finish. Probably it timed out." << endl; PUT_LOG( g_LogLevel,"The script was aborted before it could finish. Probably it timed out.\n" ); break; case  asEXECUTION_EXCEPTION: cout << "The script ended with an exception." << endl; PUT_LOG( g_LogLevel,"The script ended with an exception.\n" ); //共通エラーメッセージ CommonErrorMsg(); break; case asEXECUTION_ERROR: cout << "The script ended with an exception error." << endl; PUT_LOG( g_LogLevel,"The script ended with an exception error.\n" ); //共通エラーメッセージ CommonErrorMsg(); default: cout << "Unknown error " << endl; PUT_LOG( g_LogLevel,"Unknown error.\n" ); break; } } //angelscript内の関数に時間がかかる場合はabortを投げて例外終了させる void LineCallback2( asIScriptContext *ctx, DWORD *timeOut ) { // If the time out is reached we abort the script if( *timeOut < timeGetTime() ) { ctx->Abort(); } // It would also be possible to only suspend the script, // instead of aborting it. That would allow the application // to resume the execution where it left of at a later // time, by simply calling Execute() again. } //angelscript前にタイムアウト時間やmapにあるangelscriptのfuncIDを取得する。 int CAngelScriptMgr::Before_Excute( int index ) { int iRet = OK; CAngelMap mapdata; //int ifuncid = m_mapAngelfunc[string(chFunc)]; mapdata = m_mapAngelfunc[index]; // Create our context, prepare it, and then execute m_pasctx = m_pasengine->CreateContext(); //anglescriptの関数を実行するための準備 m_pasctx->Prepare( mapdata.iAngelFuncID ); // We don't want to allow the script to hang the application, e.g. with an // infinite loop, so we'll use the line callback function to set a timeout // that will abort the script after a certain time. Before executing the // script the timeOut variable will be set to the time when the script must // stop executing. DWORD timeOut; iRet = m_pasctx->SetLineCallback( asFUNCTION( LineCallback2 ), &timeOut, asCALL_CDECL ); if( iRet < 0 ) { cout << "Failed to set the line callback function." << endl; PUT_LOG( g_LogLevel,"Failed to set the line callback function.\n" ); return NG; } // Set the timeout before executing the function. Give the function 1 sec // to return before we'll abort it. // timeoutは1秒(1000ミリ秒)にしておく。SetScriptTimeOutで指定されていればその値 timeOut = timeGetTime() + m_dwTimeOut; return iRet; } int CAngelScriptMgr::Excute( int index, int &iret ) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { iret = m_pasctx->GetReturnDWord(); } return iRet; } //この関数では戻り値float,引数なしの関数を実行する //indexにしていするのはAngelFuncList[]のインデックス値 int CAngelScriptMgr::Excute( int index, float &fret ) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { fret = m_pasctx->GetReturnFloat(); } return iRet; } //この関数では戻り値float,引数なしの関数を実行する //indexにしていするのはAngelFuncList[]のインデックス値 int CAngelScriptMgr::Excute( int index,double &dret ) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { dret = m_pasctx->GetReturnDouble(); } return iRet; } //この関数では戻り値byte,引数なしの関数を実行する //indexにしていするのはAngelFuncList[]のインデックス値 int CAngelScriptMgr::Excute( int index,BYTE &byte ) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { byte = m_pasctx->GetReturnByte(); } return iRet; } //この関数では戻り値WORD,引数なしの関数を実行する //indexにしていするのはAngelFuncList[]のインデックス値 int CAngelScriptMgr::Excute( int index,WORD &word ) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { word = m_pasctx->GetReturnWord(); } return iRet; } //この関数では戻り値WORD,引数なしの関数を実行する //indexにしていするのはAngelFuncList[]のインデックス値 int CAngelScriptMgr::Excute( int index,DWORD &dword ) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { dword = m_pasctx->GetReturnDWord(); } return iRet; } //angelscritの引数をセットする int CAngelScriptMgr::Excute( int index,CMoveObject *ret ) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angelscriptに引数をセット,複数の引数にする場合クラスにまとめた方がよさそう //angelscriptの第1引数は0,第2引数は1を指定する。 //引数リストを別クラスにしてある場合はvoid*にキャストしてからangelscriptの関数の引数に登録する。 iRet = m_pasctx->SetArgObject( 0,(void*)ret ); if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { //void*にキャストした後CMoveObject*にする必要がある *ret = *(CMoveObject*)(void*)m_pasctx->GetReturnObject(); } return iRet; } //DWORD(int,long,word,dword)の値を引数にしてangelscript int CAngelScriptMgr::Excute( int index,DWORD *dret, DWORD dwarg0, DWORD dwarg1, DWORD dwarg2 ) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angelscriptに引数をセット,複数の引数にする場合クラスにまとめた方がよさそう //angelscriptの第1引数は0,第2引数は1を指定する。 //引数リストを別クラスにしてある場合はvoid*にキャストしてからangelscriptの関数の引数に登録する。 //iRet = m_pasctx->SetArgObject( 0,(void*)ret ); if( dwarg0 != -1 ) { iRet =  m_pasctx->SetArgDWord( 0,dwarg0 ); assert( iRet >= 0 ); } if( dwarg0 != -1 && dwarg1 != -1 ) { iRet =  m_pasctx->SetArgDWord( 0,dwarg1 ); assert( iRet >= 0 ); } if( dwarg0 != -1 && dwarg1 != -1 && dwarg2 != -1 ) { iRet =  m_pasctx->SetArgDWord( 0,dwarg2 ); assert( iRet >= 0 ); } if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { //void*にキャストした後CMoveObject*にする必要がある *dret = m_pasctx->GetReturnDWord(); } return iRet; } //floatの値を引数、戻り値もfloatのangelscriptを実行 int CAngelScriptMgr::Excute( int index,float *fret, float farg0, float farg1, float farg2) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angelscriptに引数をセット,複数の引数にする場合クラスにまとめた方がよさそう //angelscriptの第1引数は0,第2引数は1を指定する。 //引数リストを別クラスにしてある場合はvoid*にキャストしてからangelscriptの関数の引数に登録する。 //iRet = m_pasctx->SetArgObject( 0,(void*)ret ); if( farg0 != -1 ) { iRet =  m_pasctx->SetArgFloat( 0,farg0 ); assert( iRet >= 0 ); } if( farg0 != -1 && farg1 != -1 ) { iRet =  m_pasctx->SetArgFloat( 0,farg1 ); assert( iRet >= 0 ); } if( farg0 != -1 && farg1 != -1 && farg2 != -1 ) { iRet =  m_pasctx->SetArgFloat( 0,farg2 ); assert( iRet >= 0 ); } if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { //void*にキャストした後CMoveObject*にする必要がある *fret = m_pasctx->GetReturnFloat(); } return iRet; } //関数の成功、失敗を確認しないバージョン,angelscriptでアップでーとした値は第2引数に格納する。 //この関数はうまく動作していない int CAngelScriptMgr::Excute2( int index,CMoveObject &ret) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angelscriptに引数をセット,複数の引数にする場合クラスにまとめた方がよさそう //angelscriptの第1引数は0,第2引数は1を指定する。 //引数リストを別クラスにしてある場合はvoid*にキャストしてからangelscriptの関数の引数に登録する。 iRet = m_pasctx->SetArgObject( 0,(void*)&ret ); if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { //void*にキャストした後CMoveObject*にする必要がある //*ret = *(CMoveObject*)(void*)m_pasctx->GetReturnObject(); } return OK; } int CAngelScriptMgr::GetAngelFuncNum() { return m_mapAngelfunc.size(); } int CAngelScriptMgr::SetAngelFuncMap() { int iRet = OK; int iangelfuncnum = 0; for( int i = 0; i < ANGEL_SCRIPT_NUM; i++) { //buildに成功したangelscriptのみ読み込み if( ScriptList[i].bsuccess == true ) { LoadScript( ScriptList[i].scriptname ); iangelfuncnum++; } } //使用できるangelscriptのみモジュールとしてbuild BuildAngelScript(); for( int i = 0; i < ANGEL_FUNC_NUM; i++) { //anglescript内でのc++の関数のfuncidを取得しておく int ifuncid = m_pasmod->GetFunctionIdByDecl( AngelFuncList[i].chFuncID ); if( ifuncid < 0 ) {   printf("The script must have the function %s. Please add it and try again.\n",AngelFuncList[i].chFuncID );   PUT_LOG( g_LogLevel,"The script must have the function %s. Please add it and try again.\n",AngelFuncList[i].chFuncID );   continue; } CAngelMap angeldata; angeldata.iAngelFuncID = ifuncid; angeldata.strFuncName = string( AngelFuncList[i].chFuncID ); m_mapAngelfunc[i] = angeldata; } return iRet; } int CAngelScriptMgr::CheckBuild() { int iRet = OK; for( int i = 0; i < ANGEL_SCRIPT_NUM; i++) { iRet = LoadScript( ScriptList[i].scriptname ); if( iRet == OK ) { iRet = BuildAngelScript(); if( iRet == OK ) { //angelscriptのビルドに成功したらtrueに設定しておく ScriptList[i].bsuccess = true; } else { printf("faile build script name %s\n",ScriptList[i].scriptname ); PUT_LOG( g_LogLevel,"faile build script name %s\n",ScriptList[i].scriptname ); } } } return iRet; } int CAngelScriptMgr::LoadScript( char *ScriptName ) { int iRet = OK; FILE *f = fopen(ScriptName, "rb"); if ( f == NULL ) { printf(" file not found\n"); PUT_LOG( g_LogLevel,"file not found\n"); return NG; } fseek(f, 0, SEEK_END); //file sizeを取得する int len = ftell( f ); fseek( f, 0, SEEK_SET ); std::string script; script.resize(len); size_t c = fread( &script[0], len, 1, f ); fclose(f); //scriptのファイル名でセクションを登録する。 iRet = m_pasmod->AddScriptSection( ScriptName, &script[0], len ); return iRet; } //この関数はangelscriptひとつひとつチェックした後 //buildに成功したすべてのangelscriptをモジュールとして再Buildする。 int CAngelScriptMgr::BuildAngelScript() { int iRet = OK; iRet = m_pasmod->Build(); if( iRet < 0 ) { printf("angel script build failed\n" ); PUT_LOG( g_LogLevel,"angel script build failed\n"); return NG; } return iRet; } void MessageCallback2( 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); PUT_LOG( g_LogLevel,"%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message ); } void print2( string &msg ) { std::cout << msg << std::endl; } void print2( int num ) { std::cout << num << std::endl; } void print2( asUINT num ) { std::cout << num << std::endl; } void print2( float num ) { std::cout << num << std::endl; } void print2( double num ) { std::cout << num << std::endl; } //retutn int int myDrawLine( int x1 , int y1 , int x2 , int y2 ,int Color ) { int iRet = DrawLine( x1, y1, x2, y2, Color ); return iRet; } int myDrawBox( int x1 , int y1 , int x2 , int y2 ,int Color , int FillFlag ) { int iRet = DrawBox(  x1 ,  y1 ,  x2 ,  y2 , Color ,  FillFlag ); return iRet; } int myDrawCircle( int x , int y , int r , int Color, int FillFlag ) { int iRet = DrawCircle(  x ,  y ,  r ,  Color,  FillFlag ); return iRet; } int myDrawOval( int x , int y , int rx , int ry , int Color , int FillFlag ) { int iRet = DrawOval(  x ,  y ,  rx ,  ry ,  Color ,  FillFlag ) ; return iRet; } int myDrawTriangle( int x1,int y1,int x2,int y2,int x3,int y3,int Color,int FillFlag ) { int iRet = DrawTriangle( x1, y1, x2, y2, x3, y3, Color, FillFlag ) ; return iRet; } int myDrawPixel( int x, int y, int Color ) { int iRet = DrawPixel(  x ,  y ,  Color ) ; return iRet; } int CAngelScriptMgr::RegisterProperty() { int iRet = OK; iRet = m_pasengine->RegisterGlobalProperty("float g_fdata", &g_fdata); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalProperty("float g_fx", &g_fx); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalProperty("float g_fy", &g_fy); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalProperty("int gg_itimer", &gg_itimer); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalProperty("float[] @floatArray", &floatArray); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalProperty("string[] @stringArray",&stringArray); assert( iRet >= 0 ); return iRet; } int CAngelScriptMgr::RegisterMyClass() { //CMoveObject.hにあるクラスを登録 int iRet = OK; iRet = m_pasengine->RegisterObjectType("CMoveObject", sizeof(CMoveObject), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fx", offsetof(CMoveObject, fx)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fy", offsetof(CMoveObject, fy)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fwidth", offsetof(CMoveObject, fwidth)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fheight", offsetof(CMoveObject, fheight)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fhitradius", offsetof(CMoveObject, fhitradius)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float facceleration", offsetof(CMoveObject, facceleration)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fdirection", offsetof(CMoveObject, fdirection)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fspeed", offsetof(CMoveObject, fspeed)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fangle", offsetof(CMoveObject, fangle)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float finterval", offsetof(CMoveObject, finterval)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float flevel", offsetof(CMoveObject, flevel)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fkind", offsetof(CMoveObject, fkind)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fcolor", offsetof(CMoveObject, fcolor)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float falpha", offsetof(CMoveObject, falpha)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float falive", offsetof(CMoveObject, falive)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fscale", offsetof(CMoveObject, fscale)); assert( iRet >= 0 ); return iRet; } int CAngelScriptMgr::InitializeAngelEngine() { PUT_LOG( g_LogLevel,"start\n" ); int iRet = OK; // Create the script engine m_pasengine = asCreateScriptEngine(ANGELSCRIPT_VERSION); //SHIFT-JIS対応 m_pasengine->SetEngineProperty(asEP_SCRIPT_SCANNER ,0); // Set the message callback to receive information on errors in human readable form. // It's recommended to do this right after the creation of the engine, because if // some registration fails the engine may send valuable information to the message // stream. iRet = m_pasengine->SetMessageCallback( asFUNCTION( MessageCallback2 ), 0, asCALL_CDECL ); assert( iRet >= 0 ); if( iRet < 0 ) { printf("failed Message Callback\n" ); PUT_LOG( g_LogLevel,"failed Message Callback\n" ); return NG; } m_pasmod = m_pasengine->GetModule( 0, asGM_ALWAYS_CREATE ); if( iRet < 0 ) { printf("failed GetModule\n" ); PUT_LOG( g_LogLevel,"failed GetModule\n" ); return NG; } // AngelScript doesn't have a built-in string type, as there is no definite standard // string type for C++ applications. Every developer is free to register it's own string type. // The SDK do however provide a standard add-on for registering a string type, so it's not // necessary to implement the registration yourself if you don't want to. RegisterStdString( m_pasengine ); //anglescript側でprint(string),print(型)でそれぞれの値を表示できるようにする。print系は複数 //GUIやwindow関連では以下のprint関数は使えないため無意味 iRet = m_pasengine->RegisterGlobalFunction( "void print(const string &in)", asFUNCTIONPR(print2, (string &in), void), asCALL_CDECL ); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalFunction( "void print(int)", asFUNCTIONPR(print2, (int), void), asCALL_CDECL ); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalFunction( "void print(float)", asFUNCTIONPR(print2, (float), void), asCALL_CDECL ); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalFunction( "void print(uint)", asFUNCTIONPR(print2, (asUINT), void), asCALL_CDECL ); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalFunction( "void print(double)", asFUNCTIONPR(print2, (double), void), asCALL_CDECL ); assert( iRet >= 0 ); RegisterDxLibFunction(); RegisterScriptAny( m_pasengine ); // Add the support for co-routines m_pcontextMgr = new CContextMgr(); m_pcontextMgr->RegisterCoRoutineSupport( m_pasengine ); return iRet; } int  CAngelScriptMgr::RegisterDxLibFunction() { //DxLibの関数をAngelScriptから呼べるようにする //命名規則はmy<DxLib関数名>で登録する int iRet = -1; //DxLibのDrawLineの登録 iRet = m_pasengine->RegisterGlobalFunction( "int DrawLine(int, int, int, int, int )", asFUNCTIONPR(myDrawLine, (int, int, int, int, int), int), asCALL_CDECL ); assert( iRet >= 0 ); //DxLibのDrawBoxの登録 iRet = m_pasengine->RegisterGlobalFunction( "int DrawBox( int, int, int, int, int, int )", asFUNCTIONPR(myDrawBox, ( int, int, int, int, int, int ), int), asCALL_CDECL ); assert( iRet >= 0 ); //DxLibのDrawCircleの登録 iRet = m_pasengine->RegisterGlobalFunction( "int DrawCircle( int, int, int, int, int )", asFUNCTIONPR(myDrawCircle, ( int, int, int, int, int ), int), asCALL_CDECL ); assert( iRet >= 0 ); //DxLibのDrawOvalの登録 iRet = m_pasengine->RegisterGlobalFunction( "int DrawOval( int, int, int, int, int, int )", asFUNCTIONPR(myDrawOval, ( int, int, int, int, int, int ), int), asCALL_CDECL ); assert( iRet >= 0 ); //DxLibのDrawTriangleの登録 iRet = m_pasengine->RegisterGlobalFunction( "int DrawTriangle( int, int, int, int, int, int, int, int )", asFUNCTIONPR(myDrawTriangle, ( int, int, int, int, int, int, int, int ), int), asCALL_CDECL ); assert( iRet >= 0 ); //DxLibのDrawPixelの登録 iRet = m_pasengine->RegisterGlobalFunction( "int DrawPixel( int, int, int )", asFUNCTIONPR(myDrawPixel, ( int, int, int ), int), asCALL_CDECL ); assert( iRet >= 0 ); return iRet; } void CAngelScriptMgr::SetScriptTimeOut( DWORD dwMsec ) { //angelscriptの実行タイムアウト設定 m_dwTimeOut = dwMsec; } DWORD CAngelScriptMgr::GetScriptTimeOut() { //angelscriptのタイムアウト時間 return m_dwTimeOut; } </textarea>

</form> <form>

DxLibの関数をよぶangelscript

<textarea rows="8" cols="75" readonly="readonly"> //このスクリプトはDxLibの関数を呼び出しように使う //それ以外の関数はここでは登録しない void DxLibFuncTest() { // DrawLine( 0, 0, 400,500 ,248 ); // DrawBox( 400 , 100 , 20 , 20 ,100 , 1 ); // DrawCircle( 300 , 300 , 3 , 200, 0 ); // DrawOval( 300, 20 , 45 , 45 ,128 , 0 ); // DrawTriangle( 20,20,100,100,200,200,128,0 ); // DrawPixel( 100,200,255 ); } int DrawLine_Test() { return DrawLine( 0, 0, 400,500 ,128 ); } int DrawBox_Test() { return DrawBox( 400 , 100 , 20 , 20 ,100 , 1 ); } int DrawCircle_Test() { return DrawCircle( 300 , 300 , 3 , 200, 0 ); } int DrawOval_Test() { return DrawOval( 300, 200 , 45 , 45 ,128 , 0 ); } int DrawTriangle_Test() { return DrawTriangle( 200,20,100,100,300,200,128,0 ); } int DrawPixel_Test() { return DrawPixel( 300,290,128 ); } </textarea>

</form>

cppで定義した配列をangelscriptの引数に渡す

2010-02-28 17:00:21 | インポート

いろいろ試してみたけどcppで定義した配列をそのままangelscriptには登録できないみたいです。
angelscript.hで定義されている以下の型のみcppからanglescriptで定義されている関数の引数として設定できる。

・cppからangelscriptで定義された関数の引数を登録するために使用される関数。argは関数の何番目の引数か指定する。 第1引数の場合argには0を設定する。
SetArgByte(asUINT arg, asBYTE value) = 0;   
SetArgWord(asUINT arg, asWORD value) = 0; 
SetArgDWord(asUINT arg, asDWORD value) = 0;
SetArgQWord(asUINT arg, asQWORD value) = 0;
SetArgFloat(asUINT arg, float value) = 0;    
SetArgDouble(asUINT arg, double value) = 0;
SetArgAddress(asUINT arg, void *addr) = 0;
SetArgObject(asUINT arg, void *obj) = 0;


angelscript内部で配列を使用する

2010-02-21 16:21:45 | インポート
angelscript内部で配列を使用するにはRegisterGlobalPropertyでそれぞれの型の配列を使うということを示す必要がある。 スクリプト単体での配列の使用ほうほうがわかったがC++との連携方法がよくわからない。 DxLibやSeleneでサウンドやイメージを読み込んだときハンドルを保持する必要があるが、そのハンドルをスクリプト側に 渡す方法を模索中。

angelscript内部で配列を使用する。(cpp)

angelscript内部で配列を使用する。(as)

angelscript内部で配列を使用する。(angelscriptのsample改造版)(as)


<form>

angelscript内部で配列を使用する。(cpp)

<textarea readonly="readonly" cols="75" rows="8">//scriptarray test asIScriptArray *floatArray = 0; iRet = m_pasengine->RegisterGlobalProperty("float[] @floatArray", &floatArray); assert( iRet >= 0 ); </textarea>

</form>
<form>

angelscript内部で配列を使用する。(as)

<textarea readonly="readonly" cols="75" rows="8">void test() {     float[] a(2);     a[0] = 1.8f; } </textarea>

</form>
<form>

angelscript内部で配列を使用する。(angelscriptのsample改造版)

<textarea readonly="readonly" cols="75" rows="8">#include <iostream>  // cout #include <assert.h>  // assert() #include <string.h>  // strstr() #ifdef _LINUX_ #include <sys/time.h> #include <stdio.h> #include <termios.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #else #include <conio.h>   // kbhit(), getch() #include <windows.h> // timeGetTime() #include <crtdbg.h>  // debugging routines #endif #include <angelscript.h> #include "../../../add_on/scriptstring/scriptstring.h" using namespace std; #ifdef _LINUX_ #define UINT unsigned int typedef unsigned int DWORD; int ch; // Linux doesn't have timeGetTime(), this essintially does the same // thing, except this is milliseconds since Epoch (Jan 1st 1970) instead // of system start. It will work the same though... DWORD timeGetTime() { timeval time; gettimeofday(&time, NULL); return time.tv_sec*1000 + time.tv_usec/1000; } // Linux does have a getch() function in the curses library, but it doesn't // work like it does on DOS. So this does the same thing, with out the need // of the curses library. int getch() { return ch; } // kbhit() for linux int kbhit() { struct termios oldt, newt; int ch; int oldf; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newt); oldf = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); fcntl(STDIN_FILENO, F_SETFL, oldf); if(ch != EOF) { ungetc(ch, stdin); return 1; } return 0; } #endif // Function prototypes void ConfigureEngine(asIScriptEngine *engine); int  CompileScript(asIScriptEngine *engine); void PrintString(string &str); void LineCallback(asIScriptContext *ctx, DWORD *timeOut); void PrintString_Generic(asIScriptGeneric *gen); void timeGetTime_Generic(asIScriptGeneric *gen); void print(float num); //scriptarray test asIScriptArray *floatArray = 0; asIScriptArray *stringArray = 0; 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); } int main(int argc, char **argv) { int r; // Create the script engine asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); if( engine == 0 ) { cout << "Failed to create script engine." << endl; return -1; } // The script compiler will send any compiler messages to the callback engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL); // Configure the script engine with all the functions, // and variables that the script should be able to use. ConfigureEngine(engine); // Compile the script code r = CompileScript(engine); if( r < 0 ) return -1; // Create two contexts, one will run the script thread // that executes the main function, the other will other // be used to execute the event functions as needed. // Note that the global variables declared in the script // are shared between the contexts, so they are able to // communicate with each other this way. asIScriptContext *mainCtx = engine->CreateContext(); if( mainCtx == 0 ) { cout << "Failed to create the context." << endl; return -1; } asIScriptContext *eventCtx = engine->CreateContext(); if( eventCtx == 0 ) { cout << "Failed to create the context." << endl; return -1; } // Prepare the script context with the function we wish to execute r = mainCtx->Prepare(engine->GetModule(0)->GetFunctionIdByDecl("void main()")); if( r < 0 ) { cout << "Failed to prepare the context." << endl; return -1; } // Get the function IDs for the event functions already int onKeyPressID = engine->GetModule(0)->GetFunctionIdByDecl("void OnKeyPress()"); int onQuitID = engine->GetModule(0)->GetFunctionIdByDecl("void OnQuit()"); // Set the line callback so that we can suspend the script execution // after a certain time. Before executing the script the timeOut variable // will be set to the time when the script must stop executing. This // way we will be able to do more than one thing, almost at the same time. DWORD timeOut; r = mainCtx->SetLineCallback(asFUNCTION(LineCallback), &timeOut, asCALL_CDECL); if( r < 0 ) { cout << "Failed to set the line callback function." << endl; return -1; } // Print some useful information and start the input loop cout << "Sample event driven script execution using AngelScript " << asGetLibraryVersion() << "." << endl; cout << "The main script continuosly prints a short string." << endl; cout << "Press any key to fire an event that will print another string." << endl; cout << "Press ESC to terminate the application." << endl << endl; DWORD time = timeGetTime(); DWORD quitTimeOut = 0; for(;;) { // Check if any key was pressed if( kbhit() ) { int key = getch(); if( key != 27 ) { // Fire an event by calling the script function. eventCtx->Prepare(onKeyPressID); eventCtx->Execute(); // Note, I'm being a little lazy here, since we don't // verify the return codes. Neither do I add any safeguard // against never ending scripts, which if the script is // badly written could cause the program to hang, I do this // for the main script though. } else { // Fire the quit event that will tell the main script to finish eventCtx->Prepare(onQuitID); eventCtx->Execute(); // Let the script run for at most 1sec more, to give it time // to quit graciously. If it does not finish in time the // script will be aborted. quitTimeOut = timeGetTime() + 1000; } } // Allow the long running script to execute for 10ms timeOut = timeGetTime() + 10; r = mainCtx->Execute(); if( r != asEXECUTION_SUSPENDED ) { if( quitTimeOut == 0 ) cout << "The script execution finished early." << endl; break; } if( quitTimeOut && quitTimeOut < timeGetTime() ) { // Abort the long running script. // AngelScript makes sure everything is correctly freed. mainCtx->Abort(); break; } } // We must release the contexts when no longer using them mainCtx->Release(); eventCtx->Release(); // Release the engine engine->Release(); return 0; } void ConfigureEngine(asIScriptEngine *engine) { int r; // Register the script string type // Look at the implementation for this function for more information  // on how to register a custom string type, and other object types. // The implementation is in "/add_on/scriptstring/scriptstring.cpp" RegisterScriptString(engine); // Register the functions that the scripts will be allowed to use if( !strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) { r = engine->RegisterGlobalFunction("void Print(string &in)", asFUNCTION(PrintString), asCALL_CDECL); assert( r >= 0 ); r = engine->RegisterGlobalFunction("uint GetSystemTime()", asFUNCTION(timeGetTime), asCALL_STDCALL); assert( r >= 0 ); } else { r = engine->RegisterGlobalFunction("void Print(string &in)", asFUNCTION(PrintString_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterGlobalFunction("uint GetSystemTime()", asFUNCTION(timeGetTime_Generic), asCALL_GENERIC); assert( r >= 0 ); } //add arraytest start r = engine->RegisterGlobalProperty("float[] @floatArray", &floatArray); assert( r >= 0 ); r = engine->RegisterGlobalProperty("string[] @stringArray", &floatArray); assert( r >= 0 ); r = engine->RegisterGlobalFunction("void print(float)", asFUNCTIONPR(print, (float), void), asCALL_CDECL); assert( r >= 0 ); //add arraytestend } int CompileScript(asIScriptEngine *engine) { int r; // This script prints a char approximately 10 times per second const char *scriptMain = "string char = \"-\";               " "bool doQuit = false;               " "void main()                        " "{                                  " "float[] a(2);                 " "a[0]=2.1f;                     " "print(a[0]);                 " "string[] b(2);                 " "b[0]=\"arraytest\\n\";         " "Print(b[0]);                 " "  uint time = GetSystemTime();     " "  while( !doQuit )                 " "  {                                " "    uint t = GetSystemTime();      " "    if( t - time > 100 )           " "    {                              " "      time = t;                    " "      Print(char);                 " "    }                              " "  }                                " "}                                  "; const char *scriptEvents = "void OnKeyPress()                  " "{                                  " "  Print(\"A key was pressed\\n\"); " "  if( char == \"-\" )              " "    char = \"+\";                  " "  else                             " "    char = \"-\";                  " "}                                  " "void OnQuit()                      " "{                                  " "  doQuit = true;                   " "}                                  "; // Add the script sections that will be compiled into executable code asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); r = mod->AddScriptSection("scriptMain", scriptMain, strlen(scriptMain)); if( r < 0 ) { cout << "AddScriptSection() failed" << endl; return -1; } r = mod->AddScriptSection("scriptEvents", scriptEvents, strlen(scriptEvents)); if( r < 0 ) { cout << "AddScriptSection() failed" << endl; return -1; } // Compile the script r = mod->Build(); if( r < 0 ) { cout << "Build() failed" << endl; return -1; } return 0; } void print(float num) { std::cout << num << std::endl; } void PrintString(string &str) { cout << str; } void PrintString_Generic(asIScriptGeneric *gen) { string *str = (string*)gen->GetArgAddress(0); PrintString(*str); } void timeGetTime_Generic(asIScriptGeneric *gen) { gen->SetReturnDWord(timeGetTime()); } void LineCallback(asIScriptContext *ctx, DWORD *timeOut) { // If the time out is reached we suspend the script if( *timeOut < timeGetTime() ) ctx->Suspend(); } </textarea>

</form>

study angelscript 3(setter,geter)

2009-12-19 20:08:15 | インポート

angelscriptでsetter,getterを使用する。
本家の掲示板から以下のようにすればC#のようなproperty(setter,getter)を使用できる。Version 2.17.1以降。
(angelscriptコードのみ,CやC++のバインド関係とは関係ない。)
getterはget_[property]で定義して,setterはset_[property]で定義する。
([property]は自分の好きなプロパティ名)
getterはget_only,setterはset_only専用メソッド
property使用方法


angelscript_array

2009-12-19 18:06:27 | インポート

// Main class declaration
class MyClass {
public:
    int variable[128];
};

// C++ class instance
MyClass mc;


// Getter proxy
int Proxy_getvariable(const MyClass * myclass, int index) {
    if ((index) > sizeof(myclass->variable) / sizeof(myclass->variable[0]))
        asGetActiveContext()->SetException("Index out of bounds!");
    return myclass->variable[index];
}

// Setter proxy
void Proxy_setvariable(MyClass * myclass, const int& newint, int index) {
    if ((index) > sizeof(myclass->variable) / sizeof(myclass->variable[0]))
        asGetActiveContext()->SetException("Index out of bounds!");
    myclass->variable[index] = newint;
}


// Angelscript class registration
r = engine->RegisterObjectType("MyClass", 0, asOBJ_REF | asOBJ_NOHANDLE); assert( r >= 0 );
r = engine->RegisterObjectMethod("MyClass", "int get_variable(int index)", asFUNCTION(Proxy_getvariable), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
r = engine->RegisterObjectMethod("MyClass", "void set_variable(const string &in, int index)", asFUNCTION(Proxy_setvariable), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
r = engine->RegisterGlobalProperty("MyClass mc", &mc); assert( r >= 0 );

// Angelscript script example
void main() {
    mc.variable[10] = 33;
}