angelscriptのconcurrentのsampleに関数ポインタを追加してみる。
*script3に関数ポインタを追加。
angelscriptのスクリプト内でfuncdefの後に戻り値、関数名、引数を定義して関数ポインタを宣言する。
funcdef int CALLBACK(int, int);
宣言した関数ポインタの変数に実際の関数を登録する。
CALLBACK @func=@add;
関数ポインタに各関数を設定する。
@funcに足し算用の関数ポインタを設定
@func=@add;
@funcに引き算用の関数ポインタを設定
@func=@sub;
@funcにかけ算用の関数ポインタを設定
@func=@mul;
@funcに割り算用の関数ポインタを設定
@func=@div;
関数ポインタのサンプル
<textarea rows="8" cols="75" readonly="readonly">#include <iostream> // cout #include <assert.h> // assert() #include <string.h> // strstr() #include <angelscript.h> #include "../../../add_on/scriptstring/scriptstring.h" #include "../../../add_on/contextmgr/contextmgr.h" #if defined(_MSC_VER) #include <crtdbg.h> #endif #ifdef _LINUX_ #include <sys/time.h> #include <stdio.h> #include <termios.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #elif defined(__APPLE__) #include <curses.h> #else #include <conio.h> // kbhit(), getch() #include <windows.h> // timeGetTime() #endif using namespace std; #ifdef _LINUX_ #define UINT unsigned int typedef unsigned int DWORD; // 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; } // 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; } #elif defined(__APPLE__) #define UINT unsigned int typedef unsigned int DWORD; // 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; } int kbhit() { if( getch() == ERR ) return 0; return 1; } #endif // Function prototypes void ConfigureEngine(asIScriptEngine *engine); int CompileScript(asIScriptEngine *engine); void PrintString(string &str); void PrintNumber(int num); 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); } CContextMgr contextManager; asIScriptEngine *engine = 0; int main(int argc, char **argv) { #if defined(_MSC_VER) _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF); _CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR); // Use _CrtSetBreakAlloc(n) to find a specific memory leak //_CrtSetBreakAlloc(924); #endif int r; // Setup the context manager contextManager.SetGetTimeCallback((TIMEFUNC_t)&timeGetTime); // Create the script engine engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); //add shis engine->SetEngineProperty(asEP_SCRIPT_SCANNER ,0); if( engine == 0 ) { cout << "Failed to create script engine." << endl; return -1; } // The script compiler will send any compiler messages to the callback function 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; //contextManager.AddContext(engine, engine->GetModule("script1")->GetFunctionIdByDecl("void main()")); //contextManager.AddContext(engine, engine->GetModule("script2")->GetFunctionIdByDecl("void main()")); //script func pointer check start contextManager.AddContext(engine, engine->GetModule("script3")->GetFunctionIdByDecl("void main()")); //script func pointer check end // Print some useful information and start the input loop cout << "This sample shows how two scripts can be executed concurrently." << endl; cout << "Both scripts voluntarily give up the control by calling sleep()." << endl; cout << "Press any key to terminate the application." << endl; for(;;) { // Check if any key was pressed if( kbhit() ) { contextManager.AbortAll(); break; } // Allow the contextManager to determine which script to execute next contextManager.ExecuteScripts(); } // 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 r = engine->RegisterGlobalFunction("void Print(string &in)", asFUNCTION(PrintString), asCALL_CDECL); assert( r >= 0 ); r = engine->RegisterGlobalFunction("void Print(int)", asFUNCTION(PrintNumber), asCALL_CDECL); assert( r >= 0 ); // Register the functions for controlling the script threads, e.g. sleep contextManager.RegisterThreadSupport(engine); } int CompileScript(asIScriptEngine *engine) { int r; // This script prints a message 3 times per second const char *script1 = "int count = 0; " "void main() " "{ " " for(;;) " " { " " Print(\"script1 methjod beign\\n \"); " " Print(\"A 日本語 カタカナ ひらがな sjis:\"); " " Print(count++); " " Print(\"\\n\"); " " Print(\"script1 methjod end\\n \"); " " sleep(333); " " } " "} "; // This script prints a message once per second const char *script2 = "int count = 0; " "void main() " "{ " " for(;;) " " { " " Print(\"script2 methjod beign\\n \"); " " Print(\" B:\"); " " Print(count++); " " Print(\"\\n\"); " " Print(\"script2 methjod end\\n \"); " " sleep(1000); " " } " "} "; //script func pointer check start const char *script3 = "funcdef int CALLBACK(int, int); \n" "CALLBACK @func=@add; \n" "int count = 0; \n" "int testcase = 0; \n" "void main() \n" "{ \n" "int ret; \n" " for(;;) \n" " { \n" " Print(\" script3 method begin \\n\"); \n" " count++; \n" " testcase = count % 4; \n" " Print(testcase); \n" " Print(\"\\n\"); \n" " switch( testcase ) \n" " { \n" " case 0: \n" " @func=@add; \n" " Print(\" func is add function.\"); \n" " break; \n" " case 1: \n" " @func=@sub; \n" " Print(\" func is sub function.\"); \n" " break; \n" " case 2: \n" " @func=@mul; \n" " Print(\" func is mul function.\"); \n" " break; \n" " case 3: \n" " @func=@div; \n" " Print(\" func is div function.\"); \n" " break; \n" " default: \n" " @func=@add; \n" " Print(\" func is add function.\"); \n" " break; \n" " } \n" " ret = func(1,count); \n" " Print(\"ret:\"); \n" " Print(ret); \n" " Print(\"\\n\"); \n" " Print(\" script3 method end \\n\"); \n" " sleep(1000); \n" " } \n" "} \n" "int add(int a, int b) \n" "{ \n" " return a + b; \n" "} \n" "int sub(int a, int b) \n" "{ \n" " return a - b; \n" "} \n" "int mul(int a, int b) \n" "{ \n" " return a * b; \n" "} \n" "int div(int a, int b) \n" "{ \n" " return a / b; \n" "} \n"; //script func pointer check end // Build the two script into separate modules. This will make them have // separate namespaces, which allows them to use the same name for functions // and global variables. asIScriptModule *mod = engine->GetModule("script1", asGM_ALWAYS_CREATE); r = mod->AddScriptSection("script1", script1, strlen(script1)); if( r < 0 ) { cout << "AddScriptSection() failed" << endl; return -1; } r = mod->Build(); if( r < 0 ) { cout << "Build() failed" << endl; return -1; } mod = engine->GetModule("script2", asGM_ALWAYS_CREATE); r = mod->AddScriptSection("script2", script2, strlen(script2)); if( r < 0 ) { cout << "AddScriptSection() failed" << endl; return -1; } r = mod->Build(); if( r < 0 ) { cout << "Build() failed" << endl; return -1; } //script func pointer check start mod = engine->GetModule("script3", asGM_ALWAYS_CREATE); r = mod->AddScriptSection("script3", script3, strlen(script3)); if( r < 0 ) { cout << "AddScriptSection() failed" << endl; return -1; } r = mod->Build(); if( r < 0 ) { cout << "Build() failed" << endl; return -1; } //script func pointer check end return 0; } void PrintString(string &str) { cout << str; } void PrintNumber(int num) { cout << num; } </textarea>
</form>
※コメント投稿者のブログIDはブログ作成者のみに通知されます