Пример #1
0
void Engine::init()
{
	_engine->SetMessageCallback(asMETHOD(Engine, messageCallback), this, asCALL_THISCALL);

	RegisterStdString(_engine);
	RegisterScriptHandle(_engine);
	RegisterScriptAny(_engine);
}
Пример #2
0
int qasCreateScriptEngine( qboolean *as_max_portability )
{
    enginehandle_t *eh;
    asIScriptEngine *engine;

    // register the global memory allocation and deallocation functions
    asSetGlobalMemoryFunctions( qasAlloc, qasFree );

    // always new

    // ask for angelscript initialization and script engine creation
    engine = asCreateScriptEngine( ANGELSCRIPT_VERSION );
    if( !engine )
        return -1;

    eh = ( enginehandle_t * )QAS_Malloc( sizeof( enginehandle_t ) );
    eh->handle = numRegisteredEngines++;
    eh->next = engineHandlesHead;
    engineHandlesHead = eh;

    eh->engine = engine;
    eh->max_portability = qfalse;

    if( strstr( asGetLibraryOptions(), "AS_MAX_PORTABILITY" ) )
    {
        QAS_Printf( "* angelscript library with AS_MAX_PORTABILITY detected\n" );
        eh->max_portability = qtrue;
    }

    if( as_max_portability )
        *as_max_portability = eh->max_portability;

    // The script compiler will write any compiler messages to the callback.
    eh->engine->SetMessageCallback( asFUNCTION( qasGenericMessageCallback ), 0, asCALL_CDECL );

    PreRegisterMathAddon( engine );
    PreRegisterScriptArrayAddon( engine, true );
    PreRegisterStringAddon( engine );
    PreRegisterDictionaryAddon( engine );
    PreRegisterTimeAddon( engine );
    PreRegisterScriptAny( engine );
    PreRegisterVec3Addon( engine );
    PreRegisterCvarAddon( engine );
    PreRegisterStringUtilsAddon( engine );

    RegisterMathAddon( engine );
    RegisterScriptArrayAddon( engine, true );
    RegisterStringAddon( engine );
    RegisterDictionaryAddon( engine );
    RegisterTimeAddon( engine );
    RegisterScriptAny( engine );
    RegisterVec3Addon( engine );
    RegisterCvarAddon( engine );
    RegisterStringUtilsAddon( engine );

    return eh->handle;
}
Пример #3
0
asIScriptEngine *qasCreateEngine( bool *asMaxPortability )
{
	asIScriptEngine *engine;

	// register the global memory allocation and deallocation functions
	asSetGlobalMemoryFunctions( qasAlloc, qasFree );

	// always new

	// ask for angelscript initialization and script engine creation
	engine = asCreateScriptEngine( ANGELSCRIPT_VERSION );
	if( !engine )
		return NULL;

	if( strstr( asGetLibraryOptions(), "AS_MAX_PORTABILITY" ) )
	{
		QAS_Printf( "* angelscript library with AS_MAX_PORTABILITY detected\n" );
		engine->Release();
		return NULL;
	}

	*asMaxPortability = false;

	// The script compiler will write any compiler messages to the callback.
	engine->SetMessageCallback( asFUNCTION( qasMessageCallback ), 0, asCALL_CDECL );
	engine->SetEngineProperty( asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT, 1 );

	PreRegisterMathAddon( engine );
	PreRegisterScriptArray( engine, true );
	PreRegisterStringAddon( engine );
	PreRegisterScriptDictionary( engine );
	PreRegisterTimeAddon( engine );
	PreRegisterScriptAny( engine );
	PreRegisterVec3Addon( engine );
	PreRegisterCvarAddon( engine );
	PreRegisterStringUtilsAddon( engine );

	RegisterMathAddon( engine );
	RegisterScriptArray( engine, true );
	RegisterStringAddon( engine );
	RegisterScriptDictionary( engine );
	RegisterTimeAddon( engine );
	RegisterScriptAny( engine );
	RegisterVec3Addon( engine );
	RegisterCvarAddon( engine );
	RegisterStringUtilsAddon( engine );

	return engine;
}
bool Test()
{
	RET_ON_MAX_PORT

	bool fail = false;
	int r;
	COutStream out;
	CBufferedOutStream bout;
//	asIScriptContext *ctx;
	asIScriptEngine *engine;
//	asIScriptModule *mod;

	// Test circular reference between grid and ref
	{
		engine = asCreateScriptEngine();
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterScriptHandle(engine);
		RegisterScriptGrid(engine);

		// Create the circular reference
		r = ExecuteString(engine, "grid<ref> a; a.resize(1,1); @a[0,0] = a;");
		if (r != asEXECUTION_FINISHED)
			TEST_FAILED;

		engine->GarbageCollect();

		asUINT currSize, totDestroy, totDetect;
		engine->GetGCStatistics(&currSize, &totDestroy, &totDetect);
		if (currSize != 0 || totDestroy != 1 || totDetect != 1)
			TEST_FAILED;

		engine->ShutDownAndRelease();
	}

	// Test empty initialization list
	// http://www.gamedev.net/topic/658849-empty-array-initialization/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		RegisterScriptGrid(engine);

		r = ExecuteString(engine, "grid<int> a = {};"); // Valid 0x0 grid
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		r = ExecuteString(engine, "grid<int> a = {{}};"); // Valid 0x1 grid
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		r = ExecuteString(engine, "grid<int> a = {{},{}};"); // Valid 0x2 grid
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Test grid object forcibly destroyed by garbage collector
	// http://www.gamedev.net/topic/657955-a-quite-specific-bug/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		RegisterScriptGrid(engine);
		RegisterScriptAny(engine);
		RegisterScriptArray(engine, false);

		asIScriptModule *mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test", 
			"class B {} \n"
			"class A \n"
			"{ \n"
			"	any a; \n"
			"	grid<B@> t(10, 10); \n"
			"	A() \n"
			"	{ \n"
			"		a.store(@this); \n"
			"	} \n"
			"} \n"
			"array<A@> arr; \n"
			"void main() \n"
			"{ \n"
			"	arr.insertLast(@A()); \n"
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		// The type B is not really garbage collected
		asITypeInfo *t = mod->GetTypeInfoByDecl("B");
		if( t == 0 || (t->GetFlags() & asOBJ_GC) )
			TEST_FAILED;

		// grid<B> is not garbage collected since B is not
		t = mod->GetTypeInfoByDecl("grid<B>");
		if( t == 0 || (t->GetFlags() & asOBJ_GC) )
			TEST_FAILED;

		// grid<B@> is however garbage collected because it is not possible to know 
		// that no class derived from B can't form a circular reference with it.
		t = mod->GetTypeInfoByDecl("grid<B@>");
		if( t == 0 || !(t->GetFlags() & asOBJ_GC) )
			TEST_FAILED;

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Test resize
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		RegisterScriptGrid(engine);
		RegisterStdString(engine);

		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		r = ExecuteString(engine,
			"grid<string> g; \n"
			"g.resize(1,1); \n"
			"g[0,0] = 'hello'; \n"
			"g.resize(2,2); \n"
			"assert( g[0,0] == 'hello' ); \n"
			"g[1,1] = 'there'; \n"
			"g.resize(1,1); \n"
			"assert( g.width() == 1 && g.height() == 1 ); \n");
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Test initialization lists
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		RegisterScriptGrid(engine);
		RegisterStdString(engine);

		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		r = ExecuteString(engine, 
			"grid<int8> g = {{1,2,3},{4,5,6},{7,8,9}}; \n"
			"assert( g[0,0] == 1 ); \n"
			"assert( g[2,2] == 9 ); \n"
			"assert( g[0,2] == 7 ); \n");
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		r = ExecuteString(engine, 
			"grid<string> g = {{'1','2'},{'4','5'}}; \n"
			"assert( g[0,0] == '1' ); \n"
			"assert( g[1,1] == '5' ); \n"
			"assert( g[0,1] == '4' ); \n");
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		r = ExecuteString(engine,
			"grid<grid<int>@> g = {{grid<int> = {{1}}, grid<int> = {{2}}}, {grid<int> = {{3}}, grid<int> = {{4}}}}; \n"
			"assert( g[0,0][0,0] == 1 ); \n"
			"assert( g[1,1][0,0] == 4 ); \n");
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
	
		engine->Release();
	}

	// Success
	return fail;
}
Пример #5
0
bool Test()
{
	bool fail = false;
	int r;
	COutStream out;
	asIScriptContext *ctx;
	asIScriptEngine *engine;
	CBufferedOutStream bout;

	// ---------------------------------------------
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptArray(engine, true);
	RegisterScriptString_Generic(engine);
	RegisterScriptAny(engine);
	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	r = engine->RegisterGlobalFunction("void SetMyAny(any@)", asFUNCTION(SetMyAny), asCALL_GENERIC); assert( r >= 0 );

	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("TestAny", script1, strlen(script1), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("%s: Failed to compile the script\n", "TestAny");
	}
	ctx = engine->CreateContext();
	r = ExecuteString(engine, "TestAny()", mod, ctx);
	if( r != asEXECUTION_FINISHED )
	{
		if( r == asEXECUTION_EXCEPTION )
			PrintException(ctx);

		TEST_FAILED;
		printf("%s: Execution failed\n", "TestAny");
	}
	if( ctx ) ctx->Release();
	engine->Release();

	//--------------------------------------------------
	// Verify that the GC can handle circles with any structures
 	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptArray(engine, true);
	RegisterScriptString_Generic(engine);
	RegisterScriptAny(engine);
	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	r = engine->RegisterGlobalFunction("void SetMyAny(any@)", asFUNCTION(SetMyAny), asCALL_GENERIC); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("TestAny", script2, strlen(script2), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("%s: Failed to compile the script\n", "TestAny");
	}
	ctx = engine->CreateContext();
	r = ExecuteString(engine, "TestAny()", mod, ctx);
	if( r != asEXECUTION_FINISHED )
	{
		if( r == asEXECUTION_EXCEPTION )
			PrintException(ctx);

		TEST_FAILED;
		printf("%s: Execution failed\n", "TestAny");
	}
	if( ctx ) ctx->Release();
	
	asUINT gcCurrentSize, gcTotalDestroyed, gcTotalDetected;
	engine->GetGCStatistics(&gcCurrentSize, &gcTotalDestroyed, &gcTotalDetected);
	engine->GarbageCollect();
	engine->GetGCStatistics(&gcCurrentSize, &gcTotalDestroyed, &gcTotalDetected);

	if( !fail )
		assert( gcCurrentSize == 8 && gcTotalDestroyed == 8 && gcTotalDetected == 7 );

	engine->Release();

	//-------------------------------------------------------
	// Don't allow const handle to retrieve()
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptArray(engine, true);
	RegisterScriptString_Generic(engine);
	RegisterScriptAny(engine);
	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	r = engine->RegisterGlobalFunction("void SetMyAny(any@)", asFUNCTION(SetMyAny), asCALL_GENERIC); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("TestAny", script3, strlen(script3), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("%s: Failed to Build()\n", "TestAny");
	}
	if( bout.buffer != "TestAny (5, 1) : Info    : Compiling void TestAny()\n"
	                   "TestAny (9, 15) : Warning : Argument cannot be assigned. Output will be discarded.\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	engine->Release();

	//--------------------------------------------------------
	// Make sure it is possible to pass any to the application
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptArray(engine, true);
	RegisterScriptString_Generic(engine);
	RegisterScriptAny(engine);
	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	r = engine->RegisterGlobalFunction("void SetMyAny(any@)", asFUNCTION(SetMyAny), asCALL_GENERIC); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("TestAny", script4, strlen(script4), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("%s: Failed to compile\n", "TestAny");
	}
	
	r = ExecuteString(engine, "TestAny()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
		printf("%s: Failed to execute\n", "TestAny");
	}

	if( myAny )
	{
		int typeId = myAny->GetTypeId();

		if( !(typeId & asTYPEID_OBJHANDLE) )
			TEST_FAILED;
		if( (typeId & asTYPEID_MASK_OBJECT) != asTYPEID_APPOBJECT )
			TEST_FAILED;

		const char *decl = engine->GetTypeDeclaration(typeId);
		if( (decl == 0) || (strcmp(decl, "string@") != 0) )
		{
			TEST_FAILED;
			printf("%s: Failed to return the correct type\n", "TestAny");
		}

		int typeId2 = engine->GetTypeIdByDecl("string@");
		if( typeId != typeId2 )
		{
			TEST_FAILED;
			printf("%s: Failed to return the correct type\n", "TestAny");
		}

		CScriptString *str = 0;
		myAny->Retrieve((void*)&str, typeId);

		if( str->buffer != "test" )
		{
			TEST_FAILED;
			printf("%s: Failed to set the string correctly\n", "TestAny");
		}

		if( str ) str->Release();

		myAny->Release();
		myAny = 0;
	}
	else
		TEST_FAILED;

	//--------------------------------------
	// Make sure the any type can store primitives as well
	r = ExecuteString(engine, "any a; a.store(1); int b; a.retrieve(b); Assert(b == 1);");
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	engine->Release();

	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		RegisterScriptMath3D(engine);
		RegisterScriptAny(engine);

		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	
		const char *script =
			"void main() \n"
			"{ \n"
			" any storage; \n"
			" storage.store(vector3(1,1,1)); \n"
			"} \n";

		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		ctx = engine->CreateContext();
		r = ExecuteString(engine, "main()", mod, ctx);
		if( r != asEXECUTION_FINISHED )
		{
			if( r == asEXECUTION_EXCEPTION )
				PrintException(ctx);
			TEST_FAILED;
		}
		ctx->Release();

		engine->Release();
	}

	// Success
 	return fail;
}
bool Test()
{
	bool fail = Test2();
	int r;
	COutStream out;
	CBufferedOutStream bout;

	// Test that removing a group doesn't remove other functions
	// http://www.gamedev.net/topic/657987-bug-new-functions-not-accessibly-by-getglobalfunctionbyindex-after-removing-different-configuration-group/
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		// register 3 script functions a(), b() and c()
		r = engine->RegisterGlobalFunction("void a()", asFUNCTION(0), asCALL_GENERIC); assert(r>=0);
		r = engine->RegisterGlobalFunction("void b()", asFUNCTION(0), asCALL_GENERIC); assert(r>=0);
		r = engine->RegisterGlobalFunction("void c()", asFUNCTION(0), asCALL_GENERIC); assert(r>=0);

		asIScriptFunction *func = engine->GetGlobalFunctionByIndex(0);
		if( func == 0 || string(func->GetName()) != "a" )
			TEST_FAILED;
		func = engine->GetGlobalFunctionByIndex(1);
		if( func == 0 || string(func->GetName()) != "b" )
			TEST_FAILED;
		func = engine->GetGlobalFunctionByIndex(2);
		if( func == 0 || string(func->GetName()) != "c" )
			TEST_FAILED;

		// Add a dynamic group, then remove it
		r = engine->BeginConfigGroup("myconfig"); assert(r>=0);
		r = engine->RegisterGlobalFunction("void x()", asFUNCTION(0), asCALL_GENERIC); assert(r>=0);
		r = engine->RegisterGlobalFunction("void y()", asFUNCTION(0), asCALL_GENERIC); assert(r>=0);
		r = engine->EndConfigGroup(); assert(r>=0);

		r = engine->RemoveConfigGroup("myconfig"); assert(r>=0);

		// original functions should still be available
		func = engine->GetGlobalFunctionByIndex(0);
		if( func == 0 || string(func->GetName()) != "a" )
			TEST_FAILED;
		func = engine->GetGlobalFunctionByIndex(1);
		if( func == 0 || string(func->GetName()) != "b" )
			TEST_FAILED;
		func = engine->GetGlobalFunctionByIndex(2);
		if( func == 0 || string(func->GetName()) != "c" )
			TEST_FAILED;

		// add some more functions in the default group
		r = engine->RegisterGlobalFunction("void d()", asFUNCTION(0), asCALL_GENERIC); assert(r>=0);
		r = engine->RegisterGlobalFunction("void e()", asFUNCTION(0), asCALL_GENERIC); assert(r>=0);
		r = engine->RegisterGlobalFunction("void f()", asFUNCTION(0), asCALL_GENERIC); assert(r>=0);

		// original functions should still be available
		func = engine->GetGlobalFunctionByIndex(0);
		if( func == 0 || string(func->GetName()) != "a" )
			TEST_FAILED;
		func = engine->GetGlobalFunctionByIndex(1);
		if( func == 0 || string(func->GetName()) != "b" )
			TEST_FAILED;
		func = engine->GetGlobalFunctionByIndex(2);
		if( func == 0 || string(func->GetName()) != "c" )
			TEST_FAILED;

		// new functions must also be available
		func = engine->GetGlobalFunctionByIndex(3);
		if( func == 0 || string(func->GetName()) != "d" )
			TEST_FAILED;
		func = engine->GetGlobalFunctionByIndex(4);
		if( func == 0 || string(func->GetName()) != "e" )
			TEST_FAILED;
		func = engine->GetGlobalFunctionByIndex(5);
		if( func == 0 || string(func->GetName()) != "f" )
			TEST_FAILED;

		engine->Release();
	}

	// Test dynamic config groups with function definitions used for callbacks
	// http://www.gamedev.net/topic/618909-assertion-failure-in-as-configgroupcpp/
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);

		engine->BeginConfigGroup("gr");
		engine->RegisterObjectType("type", 0, asOBJ_REF);
#ifndef AS_MAX_PORTABILITY
		engine->RegisterObjectBehaviour("type", asBEHAVE_ADDREF, "void f()", asMETHOD(Type,AddRef), asCALL_THISCALL);
		engine->RegisterObjectBehaviour("type", asBEHAVE_RELEASE, "void f()", asMETHOD(Type,Release), asCALL_THISCALL);
#else
		engine->RegisterObjectBehaviour("type", asBEHAVE_ADDREF, "void f()", WRAP_MFN(Type,AddRef), asCALL_GENERIC);
		engine->RegisterObjectBehaviour("type", asBEHAVE_RELEASE, "void f()", WRAP_MFN(Type,Release), asCALL_GENERIC);
#endif
		engine->RegisterFuncdef("void fun(type @)");
		engine->RegisterObjectProperty("type", "fun @callback", asOFFSET(Type,callback));
		engine->EndConfigGroup();

		asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("s", 
			"void func(type @) {} \n"
			"void main(type @t) \n"
			"{ \n"
			"  @t.callback = func; \n"
			"} \n");

		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		Type *t = new Type();

		// Call the function that sets the callback on the object
		asIScriptFunction *m = mod->GetFunctionByName("main");
		asIScriptContext *ctx = engine->CreateContext();
		ctx->Prepare(m);
		ctx->SetArgObject(0, t);
		r = ctx->Execute();
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		ctx->Release();

		// Release the engine, while the object holding the callback is still alive
		engine->Release();

		t->Release();

		// The engine will warn about the callback not being released before the engine
		if( bout.buffer != " (0, 0) : Warning : There is an external reference to an object in module 'mod', preventing it from being deleted\n"
		                   " (0, 0) : Info    : The function in previous message is named 'func'. The func type is 1\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}
	}

	//------------
	// Test global function
	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterGlobalFunction("void MyFunc()", asFUNCTION(MyFunc), asCALL_GENERIC); assert( r >= 0 );
	r = engine->EndConfigGroup(); assert( r >= 0 );

	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);
	engine->GarbageCollect();

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	bout.buffer = "";
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (1, 1) : Info    : Compiling void Test()\n"
                                 "TestDynamicConfig (3, 3) : Error   : No matching symbol 'MyFunc'\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	engine->Release();

	//----------------
	// Test global property
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterGlobalProperty("int global", (void*)1); assert( r >= 0 );
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);
	engine->GarbageCollect();

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (1, 1) : Info    : Compiling void Test()\n"
                                 "TestDynamicConfig (3, 3) : Error   : No matching symbol 'global'\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Try registering the property again
	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterGlobalProperty("int global", (void*)1); assert( r >= 0 );
	r = engine->EndConfigGroup(); assert( r >= 0 );

	engine->Release();

	//-------------
	// Test object types
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script3, strlen(script3), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);
	engine->GarbageCollect();

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script3, strlen(script3), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (1, 1) : Info    : Compiling void Test()\n"
                                 "TestDynamicConfig (3, 3) : Error   : Identifier 'mytype' is not a data type\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	engine->Release();

	//------------------
	// Test global behaviours
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	RegisterScriptString_Generic(engine);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->RegisterObjectMethod("mytype", "string@ opAdd_r(const string &in)", asFUNCTION(MyFunc), asCALL_GENERIC); assert( r >= 0 );
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script4, strlen(script4), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);
	engine->GarbageCollect();

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	// Register the type again, but without the operator overload
	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script4, strlen(script4), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (1, 1) : Info    : Compiling void Test()\n"
                                 "TestDynamicConfig (5, 9) : Error   : No matching operator that takes the types 'string&' and 'mytype' found\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	engine->Release();

	//------------------
	// Test object types held by external variable, i.e. any

	CScriptAny *any = 0;
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptAny(engine);

	engine->BeginConfigGroup("group1");
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_REF);
	r = engine->RegisterObjectBehaviour("mytype", asBEHAVE_FACTORY, "mytype @f()", asFUNCTION(Factory), asCALL_GENERIC);
	r = engine->RegisterObjectBehaviour("mytype", asBEHAVE_ADDREF, "void f()", asFUNCTION(AddRef), asCALL_GENERIC);
	r = engine->RegisterObjectBehaviour("mytype", asBEHAVE_RELEASE, "void f()", asFUNCTION(Release), asCALL_GENERIC);

	any = (CScriptAny*)engine->CreateScriptObject(engine->GetTypeInfoByName("any"));

	r = engine->RegisterGlobalProperty("any g_any", any);
	engine->EndConfigGroup();

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(0, script5);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
		TEST_FAILED;

	r = ExecuteString(engine, "Test()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}

	engine->DiscardModule(0);
	engine->GarbageCollect();

	int *o = 0;
	any->Retrieve(&o, engine->GetTypeIdByDecl("mytype@"));
	if( o == 0 )
		TEST_FAILED;
	if( --(*o) != 1 )
		TEST_FAILED;

	// The mytype variable is still stored in the any variable so we shouldn't be allowed to remove it's configuration group
	r = engine->RemoveConfigGroup("group1"); assert( r < 0 );

	any->Release();
	engine->GarbageCollect();

	// Now it should be possible to remove the group
	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	engine->Release();

	//-------------
	// Test array types
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptArray(engine, true);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("int[]", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	asITypeInfo *ot = engine->GetTypeInfoByDecl("int[]");
	if( ot->GetSubTypeId() != asTYPEID_INT32 )
		TEST_FAILED;

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script6, strlen(script6), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);
	engine->GarbageCollect();

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	engine->Release();

	//-------------
	// Test object types in struct members
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script7, strlen(script7), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);
	engine->GarbageCollect();

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script7, strlen(script7), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (3, 3) : Error   : Identifier 'mytype' is not a data type in global namespace\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	engine->Release();

	//-------------
	// Test object types in function declarations
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script8, strlen(script8), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);
	engine->GarbageCollect();

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script8, strlen(script8), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (1, 11) : Error   : Identifier 'mytype' is not a data type in global namespace\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	engine->Release();

	//-------------
	// Test object types in script arrays
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptArray(engine, true);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script9, strlen(script9), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);
	engine->GarbageCollect();

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script9, strlen(script9), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (1, 1) : Info    : Compiling void Test()\n"
                                 "TestDynamicConfig (3, 4) : Error   : Identifier 'mytype' is not a data type\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	engine->Release();


	//------------------
	// Test object types held by external variable, i.e. any
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptArray(engine, true);
	RegisterScriptAny(engine);

	engine->BeginConfigGroup("group1");
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD);

	any = (CScriptAny*)engine->CreateScriptObject(engine->GetTypeInfoByName("any"));

	r = engine->RegisterGlobalProperty("any g_any", any);
	engine->EndConfigGroup();

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script10);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
		TEST_FAILED;

	r = ExecuteString(engine, "Test()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}

	engine->DiscardModule(0);
	engine->GarbageCollect();

	CScriptArray *array = 0;
	any->Retrieve(&array, engine->GetTypeIdByDecl("mytype[]@"));
	if( array == 0 )
	{
		TEST_FAILED;
	}
	else
		array->Release();

	engine->GarbageCollect();

	// The mytype variable is still stored in the any variable so we shouldn't be allowed to remove it's configuration group
	r = engine->RemoveConfigGroup("group1"); assert( r < 0 );

	any->Release();
	engine->GarbageCollect();

	// Now it should be possible to remove the group
	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	engine->Release();

	//-------------------
	// Test references between config groups
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->BeginConfigGroup("group1");
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 );
	engine->EndConfigGroup();

	engine->BeginConfigGroup("group2");
	r = engine->RegisterGlobalFunction("void func(mytype)", asFUNCTION(0), asCALL_GENERIC); assert( r >= 0 );
	engine->EndConfigGroup();

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	r = engine->RemoveConfigGroup("group2"); assert( r <= 0 );

	r = engine->RemoveConfigGroup("group1"); assert( r <= 0 );

	engine->Release();

	//--------------------
	// Test situation where the default group references a dynamic group. It will then be impossible
	// to remove the dynamic group, but the application must still be able to release the engine.
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->BeginConfigGroup("group1");
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 );
	engine->EndConfigGroup();

	r = engine->RegisterGlobalFunction("void func(mytype)", asFUNCTION(0), asCALL_GENERIC); assert( r >= 0 );

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->Release();

	//----------------------
	// Test that it is possible to repeat the registration of the config group
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("g1"); assert( r >= 0 );
	RegisterScriptString_Generic(engine);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	r = ExecuteString(engine, "string a = \"test\""); assert( r == asEXECUTION_FINISHED );

	r = engine->GarbageCollect(); assert( r >= 0 );

	r = engine->RemoveConfigGroup("g1"); assert( r >= 0 );

	// again..
	r = engine->BeginConfigGroup("g1"); assert( r >= 0 );
	RegisterScriptString_Generic(engine);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	r = ExecuteString(engine, "string a = \"test\""); assert( r == asEXECUTION_FINISHED );

	r = engine->GarbageCollect(); assert( r >= 0 );

	r = engine->RemoveConfigGroup("g1"); assert( r >= 0 );

	engine->Release();


	//-----------------------------
	// Test that it isn't possible to register the same property in two different groups
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->BeginConfigGroup("a");

	r = engine->RegisterGlobalProperty("int a", (void*)1); assert( r >= 0 );

	engine->EndConfigGroup();

	r = engine->RegisterGlobalProperty("int a", (void*)1); assert( r < 0 );

	engine->Release();

	//------------------------------
	// Test that ExecuteString doesn't lock dynamic config groups
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("g1"); assert( r >= 0 );
	RegisterScriptString_Generic(engine);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	r = ExecuteString(engine, "string a = \"test\""); assert( r == asEXECUTION_FINISHED );

	// Garbage collect and remove config group before discarding module
	r = engine->GarbageCollect(); assert( r >= 0 );
	r = engine->RemoveConfigGroup("g1"); assert( r >= 0 );

	engine->Release();

	//-----------------------
	// Make sure the clean-up works when there a groups using types in the default group
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	RegisterStdString(engine);

	engine->BeginConfigGroup("g");
	r = engine->RegisterGlobalFunction("void SaveLesson(const string &in)", asFUNCTION(0), asCALL_GENERIC); assert( r >= 0 );
	engine->EndConfigGroup();

	engine->Release();

	//-------------------------
	// Test registering object members in a group
	// http://www.gamedev.net/topic/636396-config-groups-and-object-property-accessors/
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->RegisterObjectType("type", 0, asOBJ_REF | asOBJ_NOCOUNT);

	// TODO: It should be possible to register methods and properties in different groups from where the type itself was registered
	engine->BeginConfigGroup("g");
	engine->RegisterObjectMethod("type", "void func()", asFUNCTION(0), asCALL_GENERIC);
	engine->EndConfigGroup();

	asITypeInfo *type = engine->GetTypeInfoByName("type");
	if( type->GetMethodCount() != 1 )
		TEST_FAILED;

	r = engine->RemoveConfigGroup("g");
	if( r < 0 )
		TEST_FAILED;

	// TODO: Currently the method is not removed as the method will be placed in the same group as the type. When this changes, the method should be removed
	if( type->GetMethodCount() != 1 )
		TEST_FAILED;

	engine->Release();


	// Success
	return fail;
}
Пример #7
0
bool Test3()
{
	if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{
		printf("%s: Skipped due to AS_MAX_PORTABILITY\n", "TestRZ");
		return false;
	}

	bool fail = false;
	int r;
	COutStream out;

	const char *script =
		"interface IMyInterface { void SomeFunc(); } \n"
		"class MyBaseClass : IMyInterface { ~MyBaseClass(){ Print(); } void SomeFunc(){} } \n"
		"class MyDerivedClass : MyBaseClass \n"
		"{ \n"
		"   IMyInterface@ m_obj; \n"
		"	MyDerivedClass(){} \n"
		"	void SetObj( IMyInterface@ obj ) { @m_obj = obj; } \n"
		"	void ClearObj(){ @m_obj = null; } \n"
		"} \n"
		"void SomeOtherFunction(){}\n"
		"any@ GetClass(){ \n"
		"  MyDerivedClass x; \n"
		"  any a( @x ); \n"
		"  return a;\n"
		"} \n";

	const char *script2 = 
		"class AClass { void Blah(){} void Blah2(){} void Blah3(){} void Blah4(){} void Blah5(){} }\n"
		"void SomeBlahFunc(){ }\n";

	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

	RegisterStdString(engine);
	RegisterScriptAny(engine);

	engine->RegisterGlobalFunction( "void Print()", asFUNCTION(Print), asCALL_CDECL );

	asIScriptModule *mod = engine->GetModule( "test", asGM_ALWAYS_CREATE );
	mod->AddScriptSection("script", script);
	r = mod->Build();

	// create two instances of our classes
	int funcId = mod->GetFunctionIdByDecl( "any@ GetClass()" );
	
	asIScriptObject* objA;
	int objATypeId;
	GetClassInstance( engine, funcId, objA, objATypeId );

	asIScriptObject* objB;
	int objBTypeId;
	GetClassInstance( engine, funcId, objB, objBTypeId );

	// resolve method functions we want to call
	asIObjectType* typeA = engine->GetObjectTypeById( objATypeId );
	int setFuncId = typeA->GetMethodIdByDecl( "void SetObj( IMyInterface@ obj )" );
	int clearFuncId = typeA->GetMethodIdByDecl( "void ClearObj()" );

	// set our objB into objA
	{
		asIScriptContext* ctxt = engine->CreateContext();
		r = ctxt->Prepare( setFuncId );
		r = ctxt->SetObject( objA );
		r = ctxt->SetArgObject( 0, objB );
		r = ctxt->Execute();
		ctxt->Release();
	}

	// release objB...
	objB->Release();
	objB = NULL;
	objBTypeId = 0;

	// clear objB from objA
	{
		asIScriptContext* ctxt = engine->CreateContext();
		r = ctxt->Prepare( clearFuncId );
		r = ctxt->SetObject( objA );
		r = ctxt->Execute();
		ctxt->Release();
	}

	// release objA
	objA->Release();
	objA = NULL;
	objATypeId = 0;

	// There are still objects held alive in the GC
	unsigned int gcCount;
	engine->GetGCStatistics(&gcCount);
	assert( gcCount == 16 ); // The script class types and functions are also in the gc

	// discard the module - no longer in use
	// The module will be discarded, but the functions that the live objects use will remain
	r = engine->DiscardModule("test");	
	if( r < 0 )
		TEST_FAILED;

	// Do a couple of more builds, so that the memory freed by DiscardModule is reused otherwise 
	// the problem may not occur, as the memory is still there, even though it was freed

	// create a module
	mod = engine->GetModule( "test2", asGM_ALWAYS_CREATE );
	mod->AddScriptSection( "script", script2 );
	r = mod->Build();

	// recreate the module
	mod = engine->GetModule( "test", asGM_ALWAYS_CREATE );
	mod->AddScriptSection("script", script);
	r = mod->Build();

	// run the garbage collector to 'clean things up'
	r = engine->GarbageCollect(asGC_FULL_CYCLE);

	// Print is called by each script class' destructor, even though the module has already been discarded
	if( g_printCount != 2 )
		TEST_FAILED;

	// we're done
	engine->Release();
		

	return fail;
}
Пример #8
0
bool Test1()
{
	bool fail = false;
	int r = 0;
	COutStream out;
 	asIScriptEngine *engine;
	int refCount;

	asIScriptObject *myGame = 0;

	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
	RegisterScriptArray(engine, true);
	RegisterScriptAny(engine);

	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("script", script1, strlen(script1));
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}

	// Calling the garbage collector mustn't free the object types, even though they are not used yet
	int tid1 = engine->GetModule(0)->GetTypeIdByDecl("MyGame@[]");
	engine->GarbageCollect();
	int tid2 = engine->GetModule(0)->GetTypeIdByDecl("MyGame@[]");

	if( tid1 != tid2 )
	{
		printf("Object type was released incorrectly by GC\n");
		TEST_FAILED;
	}

	// Make sure ref count is properly updated
	asIScriptContext *ctx = engine->CreateContext();
	ctx->Prepare(engine->GetModule(0)->GetFunctionIdByName("CreateInstance"));
	r = ctx->Execute();
	if( r != asEXECUTION_FINISHED )
	{
		printf("execution failed\n");
		TEST_FAILED;
	}
	else
	{
		CScriptAny *any = *(CScriptAny**)ctx->GetAddressOfReturnValue();
		int typeId = any->GetTypeId();
		if( !(typeId & asTYPEID_OBJHANDLE) )
		{
			printf("not a handle\n");
			TEST_FAILED;
		}

		// Retrieve will increment the reference count for us
		any->Retrieve(&myGame, typeId);

		// What is the refcount?
		myGame->AddRef();
		refCount = myGame->Release();

		// GC, any, global, application
		if( refCount != 4 )
		{
			printf("ref count is wrong\n");
			TEST_FAILED;
		}

		// Clear the reference that the any object holds (this is not necessary)
		double zero = 0.0;
		any->Store(zero);

		// What is the refcount?
		myGame->AddRef();
		refCount = myGame->Release();

		// GC, global, application
		if( refCount != 3 )
		{
			printf("ref count is wrong\n");
			TEST_FAILED;
		}
	}

	// Call abort on the context to free up resources (this is not necessary)
	ctx->Abort();

	// What is the refcount?
	myGame->AddRef();
	refCount = myGame->Release();

	// GC, global, application
	if( refCount != 3 )
	{
		printf("ref count is wrong\n");
		TEST_FAILED;
	}

	// Release the context
	ctx->Release();
	ctx = 0;

	// What is the refcount?
	myGame->AddRef();
	refCount = myGame->Release();

	// GC, global, application
	if( refCount != 3 )
	{
		printf("ref count is wrong\n");
		TEST_FAILED;
	}

	// Call garbage collection
	engine->GarbageCollect();

	// What is the refcount?
	myGame->AddRef();
	refCount = myGame->Release();

	// GC, global, application
	if( refCount != 3 )
	{
		printf("ref count is wrong\n");
		TEST_FAILED;
	}

	// Discard the module, freeing the global variable
	engine->DiscardModule(0);

	// What is the refcount?
	myGame->AddRef();
	refCount = myGame->Release();

	// GC, application
	if( refCount != 2 )
	{
		printf("ref count is wrong\n");
		TEST_FAILED;
	}

	// Release the game object
	refCount = myGame->Release();

	// GC
	if( refCount != 1 )
	{
		printf("ref count is wrong\n");
		TEST_FAILED;
	}

	// Release engine
	engine->Release();
	engine = 0;

	// Success
 	return fail;
}
Пример #9
0
bool Test()
{
	bool fail = false;
	int r;

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	RegisterScriptString_Generic(engine);
	RegisterScriptAny(engine);

	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void Analyze(any &inout)", asFUNCTION(Analyze), asCALL_GENERIC);

	COutStream out;
	CBufferedOutStream bout;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	asIScriptContext *ctx = engine->CreateContext();
	r = ExecuteString(engine, "Test()", mod, ctx);
	if( r != asEXECUTION_FINISHED ) 
	{
		if( r == asEXECUTION_EXCEPTION ) PrintException(ctx);
		TEST_FAILED;
	}
	if( ctx ) ctx->Release();

	// Make sure that the error message for wrong constructor name works
	bout.buffer = "";
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, "class t{ s() {} };", 18, 0);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "TestScriptClassMethod (1, 10) : Error   : The name of constructors and destructors must be the same as the class\n" ) 
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Make sure the default constructor can be overloaded
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	r = ExecuteString(engine, "Test()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}

	asIObjectType *type = engine->GetModule("test")->GetObjectTypeByName("myclass");
	asIScriptObject *s = (asIScriptObject*)engine->CreateScriptObject(type);
	if( s == 0 ) 
		TEST_FAILED;
	else
	{
		// Validate the property
		int *v = 0;
		int n = s->GetPropertyCount();
		for( int c = 0; c < n; c++ )
		{
			std::string str = "value";
			if( str == s->GetPropertyName(c) )
			{	
				v = (int*)s->GetAddressOfProperty(c);
				if( *v != 1 ) TEST_FAILED;
			}
		}

		// Call the script class method
		if( type->GetMethodCount() != 2 ) 
			TEST_FAILED;
		asIScriptFunction *method = type->GetMethodByDecl("void method2()");
		if( method == 0 ) 
			TEST_FAILED;
		else
		{
			asIScriptContext *ctx = engine->CreateContext();
			ctx->Prepare(method);
			ctx->SetObject(s);
			int r = ctx->Execute();
			if( r != asEXECUTION_FINISHED )
				TEST_FAILED;

			if( (!v) || (*v != 3) ) 
				TEST_FAILED;

			ctx->Release();
		}

		s->Release();
	}

	engine->Release();

	//----------------------------------
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptAny(engine);
	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("test3", script3, strlen(script3), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	int typeId = engine->GetModule(0)->GetTypeIdByDecl("myclass");
	type = engine->GetObjectTypeById(typeId);
	asIScriptFunction *mtd = type->GetMethodByDecl("void func()");
	asIScriptObject *obj = (asIScriptObject *)engine->GetModule(0)->GetAddressOfGlobalVar(engine->GetModule(0)->GetGlobalVarIndexByName("c"));

	if( mtd == 0 || obj == 0 ) TEST_FAILED;
	else
	{
		asIScriptContext *ctx = engine->CreateContext();
		ctx->Prepare(mtd);
		ctx->SetObject(obj);
		r = ctx->Execute();
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;
		ctx->Release();
	}

	type = engine->GetObjectTypeById(typeId);
	mtd = type->GetMethodByDecl("void func(int, int)");
	if( mtd == 0 || obj == 0 ) TEST_FAILED;
	else
	{
		asIScriptContext *ctx = engine->CreateContext();
		ctx->Prepare(mtd);
		ctx->SetObject(obj);
		ctx->SetArgDWord(0, 1);
		ctx->SetArgDWord(1, 1);
		r = ctx->Execute();
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;
		ctx->Release();
	}

	engine->Release();

	//----------------------------
	// Verify that global functions and class methods with the same name doesn't conflict
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptAny(engine);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("test4", script4, strlen(script4), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;
	
	asIScriptFunction *func = mod->GetFunctionByDecl("void func()");
	if( func == 0 ) TEST_FAILED;

	engine->Release();

	//----------------------------
	// Accessing member variables without this
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptAny(engine);
	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("test5", script5, strlen(script5), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	r = ExecuteString(engine, "test()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}

	engine->Release();

	//-----------------------------
	// Name conflict with class method and object type
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
	RegisterScriptString(engine);
	engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_GENERIC);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("test6", script6, strlen(script6), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	outbuffer = "";
	r = ExecuteString(engine, "Test t; t.Set(1); t.Test2();", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}
	if( outbuffer != "Test::Set\nTest::Set\nSet::Set\n" )
	{
		printf("%s", outbuffer.c_str());
		TEST_FAILED;
	}

	engine->Release();

	//------------------------------
	// The scope operator should permit calling global functions if the class has a method of the same name
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
	engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	const char *script = 
		"class A { \n"
		"  void func() { \n"
		"    g = 0; \n"
		"    testScope(); \n"
		"    assert(g == 3); \n"
        "    ::testScope(); \n"
		"    assert(g == 2); \n"
		"  } \n"
        "  void testScope() { g = 3; } \n"
		"} \n"
		"void testScope() { g = 2; } \n"
		"int g; \n";
	mod->AddScriptSection("script", script);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}
	r = ExecuteString(engine, "A a; a.func(); assert( g == 2 );", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}
	engine->Release();

	//---------------------------
	// It should not be possible to declare a method with the same name as the class
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		const char *script = 
			"class A { \n"
			"  void A() {} \n"
			"} \n";
		mod->AddScriptSection("script", script);
		bout.buffer = "";
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;
		if( bout.buffer != "script (2, 3) : Error   : The method cannot be named with the class name\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}
		engine->Release();
	}

	// Success
	return fail;
}