gooブログはじめました!

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

関数ポインタのサンプル

2010-04-03 15:39:47 | angelscript

関数ポインタのサンプル

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;

<form>

関数ポインタのサンプル


<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>

コメントを投稿