Код для этого может выглядеть примерно так:
// Получаем экземпляр скриптового контекста. asIScriptContext *ctx = engine->CreateContext(); // Получение id функции из модуля. Данную величину рекомендуется сохранить, // если планируется вызывать функцию много раз. int funcId = engine->GetModule(module_name)->GetFunctionIdByDecl(function_declaration); // Подготавливаем стек ctx->Prepare(funcId); // Устанавливаем аргументы функции ctx->SetArgDWord(...); int r = ctx->Execute(); if( r == asEXECUTION_FINISHED ) { // Получаем возвращаемые значение в случае успешного завершения работы функции asDWORD ret = ctx->GetReturnDWord(); } // Очищаем контекст ctx->Release();
Если вы прервали выполнение, и функция не закончила работу и вернула asEXECUTION_SUSPENDED, вы можете продолжить ее выполнение простым вызовом этой функции.
Возвращаемое значение достается функцией GetReturnValue(), но только в случае если скрипт завершился нормально, т.е. Execute() вернула asEXECUTION_FINISHED.
int SetArgDWord(int arg, asDWORD value); int SetArgQWord(int arg, asQWORD value); int SetArgFloat(int arg, float value); int SetArgDouble(int arg, double value);
Где arg - номер аргумента, первый - 0, второй - 1, и так далее.
value - значение аргумента.
Метод задает тип параметра, для примитивных типов вы можете использовать любой из них.
Если параметр - ссылка на примитивный тип, используйте SetArgDWord() и передайте указатель на значение.
Для непримитивных типов используйте SetArgObject(), который будет описан ниже.
// Контекст подготовлен для скриптовой функции следующего вида // int function(int, double, int&in) // Указываем параметры, начиная с первого ctx->SetArgDWord(0, 1); ctx->SetArgDouble(1, 3.141592); int val; ctx->SetArgDWord(2, (asDWORD)&val);
После того как скрипт отработал, результаты получаются аналогичной группой методов GetReturn:
asDWORD GetReturnDWord(); asQWORD GetReturnQWord(); float GetReturnFloat(); double GetReturnDouble();
Помните, что вы должны быть уверены в валидности возвращаемых значений, например если выполнение скрипта вызвало ошибки, возвращаемые значения валидными не будут. Проверить валидность можно с помошью Execute() и GetState(), которые должны возвращать asEXECUTION_FINISHED.
int SetArgObject(int arg, void *object);
arg - число аргументов. object - указатель на объект.
Данный метод используется для передачи обьектов и по ссылке и по значению. Движок автоматически сделает копию параметра, если он передан по значению.
// Хотим передать обьект в функцию CObject obj; // Передаем обьект в функцию ctx->SetArgObject(0, &obj);
Получаем обьект из функции используя GetReturnObject():
void *GetReturnObject();
Данный метод вернет указатель на обьект, который вернула функция. Движок сохранит ссылку на обьект до тех пор, пока контекст не будет очищен.
// Обьект который, в который мы сохраним возвращаемое значение CObject obj; // Запускаем функцию int r = ctx->Execute(); if( r == asEXECUTION_FINISHED ) { // Получаем указатель на возвращаемый обьект и копируем его в свой obj = *(CObject*)ctx->GetReturnObject(); }
Важно делать копию возвращаемого обьекта, или, если используется механизм подсчета ссылок, увеличивать счетчик. В противном случае указатедб возвращаемый GetReturnObject() станет невалидным после очистки контекста.
Если скрипт выполнит ошибочные действия, то движок вызовет исключение. Виртуальная машина прервет исполнение и метод Execute вернет значение asEXECUTION_EXCEPTION. В это время можно получить информацию об ошибке через методы asIScriptContext.
Пример:
void PrintExceptionInfo(asIScriptContext *ctx) { asIScriptEngine *engine = ctx->GetEngine(); // Определяем причину ошибки printf("desc: %s\n", ctx->GetExceptionString()); // Определяем функцию с ошибкой int funcId = ctx->GetExceptionFunction(); const asIScriptFunction *function = engine->GetFunctionDescriptorById(funcId); printf("func: %s\n", function->GetDeclaration()); printf("modl: %s\n", function->GetModuleName()); printf("sect: %s\n", function->GetScriptSectionName()); // Определяем номер строки с ошибкой printf("line: %d\n", ctx->GetExceptionLineNumber()); }
При желании можно зарегистрировать функцию обратного вызова, которая будет вызвана в момент ошибки,до возвращения из метода Execute.