🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Strange Errors

Started by
11 comments, last by WitchLord 17 years, 9 months ago
I just want to start off by saying that I enjoy working with AngelScript. I am converting my Survival Horror game (4E5 Project) over to it from EOSScript. I am having an issue that I am not sure how to solve. My app is crashing and in my log I am getting a bunch of the following errors: System function (1, 32) : ERR : Only object types that support object handles can use &inout. Use ∈ or &out instead I know the following code is the culprit because I just added it and it worked fine before. I've gone over it repeatedly and can't find anything wrong.

// Register Constants
	g_pScriptEngine->RegisterGlobalProperty("const int JE_TRUE = 1", NULL);
	g_pScriptEngine->RegisterGlobalProperty("const int JE_FALSE = 0", NULL);

	// Register Objects
	g_pScriptEngine->RegisterObjectType("CVector3", sizeof(CVector3), 0);
	g_pScriptEngine->RegisterObjectType("CQuaternion", sizeof(CQuaternion), 0);
	g_pScriptEngine->RegisterObjectType("CXForm3d", sizeof(CXForm3d), 0);

	// Register Object methods
	g_pScriptEngine->RegisterObjectMethod("CVector3", "void Set(float x, float y, float z)", asMETHOD(CVector3, Set), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CVector3", "float GetX()", asMETHOD(CVector3, GetX), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CVector3", "float GetY()", asMETHOD(CVector3, GetY), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CVector3", "float GetZ()", asMETHOD(CVector3, GetZ), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CVector3", "float GetLength()", asMETHOD(CVector3, GetLength), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CVector3", "void Normalize()", asMETHOD(CVector3, Normalize), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CVector3", "CVector3 GetInverse()", asMETHOD(CVector3, GetInverse), asCALL_THISCALL);

	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "void Set(float x, float y, float z, float w)", asMETHOD(CQuaternion, Set), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "void SetFromAxisAngle(CVector3 &axis, float angle)", asMETHOD(CQuaternion, SetFromAxisAngle), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "CVector3 GetAxis()", asMETHOD(CQuaternion, GetAxis), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "float GetAngle()", asMETHOD(CQuaternion, GetAngle), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "CQuaternion Slerp(CQuaternion &q1, float t)", asMETHOD(CQuaternion, Slerp), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "CQuaternion SlerpNotShortest(CQuaternion &q1, float t)", asMETHOD(CQuaternion, SlerpNotShortest), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "CVector3 Rotate(CVector3 &v1)", asMETHOD(CQuaternion, Rotate), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "int IsUnit()", asMETHOD(CQuaternion, IsUnit), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "void SetNoRotation()", asMETHOD(CQuaternion, SetNoRotation), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "CQuaternion Ln()", asMETHOD(CQuaternion, Ln), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "CQuaternion Exp()", asMETHOD(CQuaternion, Exp), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "CQuaternion Scale(float scale)", asMETHOD(CQuaternion, Scale), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "CQuaternion GetInverse()", asMETHOD(CQuaternion, GetInverse), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "float Magnitude()", asMETHOD(CQuaternion, Magnitude), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "void FromMatrix(CXForm3d &xf)", asMETHOD(CQuaternion, FromMatrix), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CQuaternion", "CXForm3d ToMatrix()", asMETHOD(CQuaternion, ToMatrix), asCALL_THISCALL);

	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void Identity()", asMETHOD(CXForm3d, Identity), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void RotateX(float rads)", asMETHOD(CXForm3d, RotateX), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void RotateY(float rads)", asMETHOD(CXForm3d, RotateY), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void RotateZ(float rads)", asMETHOD(CXForm3d, RotateZ), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void Translate(CVector3 &pos)", asMETHOD(CXForm3d, Translate), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void Scale(CVector3 &scale)", asMETHOD(CXForm3d, Scale), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void SetXRotation(float rads)", asMETHOD(CXForm3d, SetXRotation), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void SetYRotation(float rads)", asMETHOD(CXForm3d, SetYRotation), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void SetZRotation(float rads)", asMETHOD(CXForm3d, SetZRotation), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void SetTranslation(CVector3 &pos)", asMETHOD(CXForm3d, SetTranslation), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void SetScaling(CVector3 &scale)", asMETHOD(CXForm3d, SetScaling), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "int IsOrthoNormal()", asMETHOD(CXForm3d, IsOrthoNormal), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "int IsOrthogonal()", asMETHOD(CXForm3d, IsOrthogonal), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void Orthonormalize()", asMETHOD(CXForm3d, Orthonormalize), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "CVector3 Transform(CVector3 &v1)", asMETHOD(CXForm3d, Transform), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "CVector3 Rotate(CVector3 &v1)", asMETHOD(CXForm3d, Rotate), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "CVector3 GetLeft()", asMETHOD(CXForm3d, GetLeft), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "CVector3 GetUp()", asMETHOD(CXForm3d, GetUp), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "CVector3 GetIn()", asMETHOD(CXForm3d, GetIn), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "CVector3 GetTranslation()", asMETHOD(CXForm3d, GetTranslation), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "CVector3 GetInverse()", asMETHOD(CXForm3d, GetInverse), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "CVector3 GetTranspose()", asMETHOD(CXForm3d, GetTranspose), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "CVector3 GetEulerAngles()", asMETHOD(CXForm3d, GetEulerAngles), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void SetEulerAngles(CVector3 &angles)", asMETHOD(CXForm3d, SetEulerAngles), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "void SetFromLeftUpIn(CVector3 &left, CVector3 &up, CVector3 &inv)", asMETHOD(CXForm3d, SetFromLeftUpIn), asCALL_THISCALL);
	g_pScriptEngine->RegisterObjectMethod("CXForm3d", "CXForm3d Mirror(CVector3 &PlaneNormal, float PlaneDist)", asMETHOD(CXForm3d, Mirror), asCALL_THISCALL);

	// Register Global Functions
	g_pScriptEngine->RegisterGlobalFunction("CVector3 Vec3d_Add(CVector3 &v1, CVector3 &v2)", asFUNCTION(Vec3d_Add), asCALL_CDECL);
	g_pScriptEngine->RegisterGlobalFunction("CVector3 Vec3d_Subtract(CVector3 &v1, CVector3 &v2)", asFUNCTION(Vec3d_Subtract), asCALL_CDECL);
	g_pScriptEngine->RegisterGlobalFunction("CVector3 Vec3d_Scale(CVector3 &v1, float scale)", asFUNCTION(Vec3d_Scale), asCALL_CDECL);
	g_pScriptEngine->RegisterGlobalFunction("CVector3 Vec3d_Cross(CVector3 &v1, CVector3 &v2)", asFUNCTION(Vec3d_Cross), asCALL_CDECL);
	g_pScriptEngine->RegisterGlobalFunction("float Vec3d_Dot(CVector3 &v1, CVector3 &v2)", asFUNCTION(Vec3d_Dot), asCALL_CDECL);
	
	g_pScriptEngine->RegisterGlobalFunction("CQuaternion Quaternion_Add(CQuaternion &q1, CQuaternion &q2)", asFUNCTION(Quaternion_Add), asCALL_CDECL);
	g_pScriptEngine->RegisterGlobalFunction("CQuaternion Quaternion_Subtract(CQuaternion &q1, CQuaternion &q2)", asFUNCTION(Quaternion_Subtract), asCALL_CDECL);
	g_pScriptEngine->RegisterGlobalFunction("CQuaternion Quaternion_Multiply(CQuaternion &q1, CQuaternion &q2)", asFUNCTION(Quaternion_Multiply), asCALL_CDECL);
	
	g_pScriptEngine->RegisterGlobalFunction("CXForm3d XForm3d_Multiply(CXForm3d &x1, CXForm3d &x2)", asFUNCTION(XForm3d_Multiply), asCALL_CDECL);


I'm not sure what they mean. Can someone point me in the right direction?
Anthony Rufrano
RealityFactory 2 Programmer
Advertisement
Ok. I figured it out. I had to change the declarations to not use references.
Anthony Rufrano
RealityFactory 2 Programmer
I'm glad you like AngelScript, and also that you figured out the problem yourself. [smile]

Anyway, you don't have to stop using parameter references entirely. You just need to tell AngelScript, how the reference is meant to be used, either as an in-value or an out-value. This is necessary so that AngelScript can guarantee the lifetime of the objects. Example:

g_pScriptEngine->RegisterObjectMethod("CQuaternion", "void SetFromAxisAngle(CVector3 ∈ axis, float angle)", asMETHOD(CQuaternion, SetFromAxisAngle), asCALL_THISCALL);


Add the 'in' keyword to the reference to tell AngelScript that the parameter value will only be used by the function, that it will not be modified and returned to the calling function.

The registered function will receive the parameter as a normal reference, so there is no need to modify the C++ code. The only difference is that the reference may not be pointing to the actual object, but instead a copy of it.

Objects that support object handles, i.e. have the AddRef and Release behaviours registered, can be passed by reference as both in and out values, i.e. without any extra keyword.

Hope that helps you understand it a little better.

Regards,
Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I will give it a shot. I am assuming that the method you gave me would allow me to use function arguments as return values also?

Let me explain what I am trying to achieve and see if AngelScript can help me:

I have a game object system very similar to that of Dungeon Siege. I have a class called CGameObject (very inventive naming) and I want to be able to implement objects in both C++ and AngelScript. The AngelScript defined objects would just use the CGameObject base class and the script would house the functions that the class needs defined. The C++ classes would derive from CGameObject and override the virtual functions. From what I see so far, AngelScript is perfect. EOSScript provided single and multiple inheritance but is not being developed any more and has a very wierd syntax.

My question is, would a class that derives from the script exposed CGameObject class in AngelScript be the right way, or would just doing it the old fashioned way (defining global functions and using modules) be better for this?

In addition, would you be able to provide me a sample of using offsetof with AngelScript?

Thanks and keep up the good work!!
Anthony Rufrano
RealityFactory 2 Programmer
Yes, you can use function arguments for return values as well. It would look like this:

// AngelScript signaturevoid GetValue(type &out retVal);// C++ signaturevoid GetValue(type &retVal); - or -void GetValue(type *retVal);


The C++ function will receive a reference to an object (initialized with the default constructor). After the function returns AngelScript will then copy the returned value into the true object.

AngelScript currently doesn't support inheritance, but I'm working on it. I'm not sure if I will be able to allow a script class to inherit from a C++ class though, but I will try to do that.

Having your C++ object inherit from CGameObject looks like a good idea. The objects that will be implemented in the scripts may need a special version of CGameObject in order to be able to call the script functions/methods when invoked from the application. I suggest you expose an interface, e.g. GameObjectIntf, to the script. The script will then implement a class with that interface. Your CGameObject can then simply instanciate that class and automatically know that all the methods are implemented, which simplifies the method calling.

The offsetof() macro is mostly used when registering the class member variables, e.g:

engine->RegisterObjectProperty("CVector3", "float x", offsetof(CVector3, x));engine->RegisterObjectProperty("CVector3", "float y", offsetof(CVector3, y));engine->RegisterObjectProperty("CVector3", "float z", offsetof(CVector3, z));


Regards,
Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Thanks for the answers. Your suggestion sounds good. I will give it a try.
Anthony Rufrano
RealityFactory 2 Programmer
Some more wierdness. I am trying to register a second singleton (SoundMgr). When I call g_pScriptEngine->RegisterGlobalProperty() on the new singleton, my gameshell crashes due to my other singleton being invalid (0xcdcdcdcd). If I remove the sound manager singleton it works fine. Do I have to define the reference counting stuff? I am not using it to pass around, I want just the one global variable in AngelScript.
Anthony Rufrano
RealityFactory 2 Programmer
I'm not sure I understand exactly what you're doing. Could you show me with a small example? It will be much easier for me to understand that way.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I have my GameMgr singleton (C++) and my SoundMgr singleton (C++). I am trying to register both singletons with AngelScript. When I register the second singleton (SoundMgr) using RegisterGlobalProperty(), my first singleton becomes invalid (0xcdcdcdcd) in AngelScript and my app crashes.

My GameMgr registers it's functions in it's constructor.

g_pScriptEngine->RegisterObjectType("GameMgr", 0, 0);	// Misc	g_pScriptEngine->RegisterObjectMethod("GameMgr", "void EnableFrameRateCounter(int enable)", asMETHOD(CGameMgr, EnableFrameRateCounter), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("GameMgr", "int GetWidth()", asMETHOD(CGameMgr, GetWidth), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("GameMgr", "int GetHeight()", asMETHOD(CGameMgr, GetHeight), asCALL_THISCALL);	// Driver stuff	g_pScriptEngine->RegisterObjectMethod("GameMgr", "int SetDriverMode(int w, int h, int b)", asMETHOD(CGameMgr, SetDriverMode), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("GameMgr", "void SetGamma(float gamma)", asMETHOD(CGameMgr, SetGamma), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("GameMgr", "float GetGamma()", asMETHOD(CGameMgr, GetGamma), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("GameMgr", "void EnableFog(float r, float g, float b, float start, float end)", asMETHOD(CGameMgr, EnableFog), asCALL_THISCALL);	// Bitmap Management	g_pScriptEngine->RegisterObjectMethod("GameMgr", "void AddBitmap(string &name, string &filename)", asMETHOD(CGameMgr, AddBitmap), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("GameMgr", "void RemoveBitmap(string &name)", asMETHOD(CGameMgr, RemoveBitmap), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("GameMgr", "bool HasBitmap(string &name)", asMETHOD(CGameMgr, HasBitmap), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("GameMgr", "bool DrawBitmap(string &name, int x, int y)", asMETHOD(CGameMgr, DrawBitmap), asCALL_THISCALL);	// Actor Def Management	g_pScriptEngine->RegisterObjectMethod("GameMgr", "void AddActorDef(string &name, string &filename)", asMETHOD(CGameMgr, AddActorDef), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("GameMgr", "void RemoveActorDef(string &name, string &filename)", asMETHOD(CGameMgr, RemoveActorDef), asCALL_THISCALL);	// Register Singleton with AngelScript	g_pScriptEngine->RegisterGlobalProperty("GameMgr Game", (void*)this);


My sound manager does the same and looks like this:

// Register Singleton with AngelScript	g_pScriptEngine->RegisterObjectType("SoundMgr", 0, 0);	g_pScriptEngine->RegisterObjectMethod("SoundMgr", "int AddSound(string &name, string &filename)", asMETHOD(CSoundMgr, AddSound), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("SoundMgr", "int Add3DSound(string &name, string &filename)", asMETHOD(CSoundMgr, Add3DSound), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("SoundMgr", "int RemoveSound(string &name)", asMETHOD(CSoundMgr, RemoveSound), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("SoundMgr", "int HasSound(string &name)", asMETHOD(CSoundMgr, HasSound), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("SoundMgr", "int PlaySound(string &name, float vol, float pan, float freq, int loop)", asMETHOD(CSoundMgr, PlaySound), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("SoundMgr", "int StopSound(string &name)", asMETHOD(CSoundMgr, StopSound), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("SoundMgr", "int ModifySound(string &name, float vol, float pan, float freq)", asMETHOD(CSoundMgr, ModifySound), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("SoundMgr", "int IsSoundPlaying(string &name)", asMETHOD(CSoundMgr, IsSoundPlaying), asCALL_THISCALL);	g_pScriptEngine->RegisterObjectMethod("SoundMgr", "int SetMasterVolume(float vol)", asMETHOD(CSoundMgr, SetMasterVolume), asCALL_THISCALL);	g_pScriptEngine->RegisterGlobalProperty("SoundMgr SMgr", (void*)this);


When I call RegisterGlobalProperty() on the SoundMgr, I can no longer access the GameMgr singleton in AngelScript. In C++ it's fine. If I remove the RegisterGlobalProperty() in the SoundMgr, everything goes back to normal. No errors are coming from AngelScript into my log.
Anthony Rufrano
RealityFactory 2 Programmer
Looks like it is a problem in AngelScript.

I'll verify this and let you know what I find.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement