1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
#include "scripthelper.h"
#include "hpl1/std/set.h"
#include "common/str.h"
using namespace std;
BEGIN_AS_NAMESPACE
int ExecuteString(asIScriptEngine *engine, const char *code, asIScriptModule *mod, asIScriptContext *ctx) {
return ExecuteString(engine, code, 0, asTYPEID_VOID, mod, ctx);
}
int ExecuteString(asIScriptEngine *engine, const char *code, void *ref, int refTypeId, asIScriptModule *mod, asIScriptContext *ctx) {
// Wrap the code in a function so that it can be compiled and executed
Common::String funcCode = " ExecuteString() {\n";
funcCode += code;
funcCode += "\n;}";
// Determine the return type based on the type of the ref arg
funcCode = engine->GetTypeDeclaration(refTypeId, true) + funcCode;
// GetModule will free unused types, so to be on the safe side we'll hold on to a reference to the type
asITypeInfo *type = 0;
if (refTypeId & asTYPEID_MASK_OBJECT) {
type = engine->GetTypeInfoById(refTypeId);
if (type)
type->AddRef();
}
// If no module was provided, get a dummy from the engine
asIScriptModule *execMod = mod ? mod : engine->GetModule("ExecuteString", asGM_ALWAYS_CREATE);
// Now it's ok to release the type
if (type)
type->Release();
// Compile the function that can be executed
asIScriptFunction *func = 0;
int r = execMod->CompileFunction("ExecuteString", funcCode.c_str(), -1, 0, &func);
if (r < 0)
return r;
// If no context was provided, request a new one from the engine
asIScriptContext *execCtx = ctx ? ctx : engine->RequestContext();
r = execCtx->Prepare(func);
if (r >= 0) {
// Execute the function
r = execCtx->Execute();
// Unless the provided type was void retrieve it's value
if (ref != 0 && refTypeId != asTYPEID_VOID) {
if (refTypeId & asTYPEID_OBJHANDLE) {
// Expect the pointer to be null to start with
assert(*reinterpret_cast<void **>(ref) == 0);
*reinterpret_cast<void **>(ref) = *reinterpret_cast<void **>(execCtx->GetAddressOfReturnValue());
engine->AddRefScriptObject(*reinterpret_cast<void **>(ref), engine->GetTypeInfoById(refTypeId));
} else if (refTypeId & asTYPEID_MASK_OBJECT) {
// Use the registered assignment operator to do a value assign.
// This assumes that the ref is pointing to a valid object instance.
engine->AssignScriptObject(ref, execCtx->GetAddressOfReturnValue(), engine->GetTypeInfoById(refTypeId));
} else {
// Copy the primitive value
memcpy(ref, execCtx->GetAddressOfReturnValue(), engine->GetSizeOfPrimitiveType(refTypeId));
}
}
}
// Clean up
func->Release();
if (!ctx) engine->ReturnContext(execCtx);
return r;
}
END_AS_NAMESPACE
|