64-bit issues with a string class

Started by
11 comments, last by WitchLord 14 years ago
I've been using AngelScript 2.18.1 in my project and so far it has been great. I've been developing it on Windows just fine. My project will be cross-platform, so I started work on the Linux version when I hit a snag. You see, my Linux computer is 64-bit, so all the libraries, compilers, etc default to 64-bit. This is when I started to run into my 64-bit issues. I had been using the scriptstdstring addon to bind std::string to AngelScript. However, do to some odd set of circumstances, AngelScript was crashing when it was trying to destruct the std::string. It was somehow related to passing it by reference. When I passed it by value, it only sort of worked. My "Update" function, which is called every frame, would silently stop working once it came across the string, yet my "OnKeyPress" function would pass the string just fine. Thinking it was a 64-bit issue, I went back to my Windows machine and had Visual Studio compile my project as a 64-bit application. I hadn't bothered to compile boost in 64-bit on Windows, so I had been developing it in 32-bit mode, and it worked great. Once I got all my libraries compiled as 64-bit, I compiled and ran my program. AngelScript passed random garbage as the string. Thinking it was just an issue with using std::string, I bound a different string class to AngelScript. This time, AngelScript passed an empty string and crashed when it tried to destruct it. This is the script that I am executing: http://nalin.pastebin.com/m7ea1ae65 In "Update", once AngelScript hit "obj.Animation = "walk.gani";", it would silently stop executing the script. However, in OnKeyPress, it would behave like normal. Is there anything I can do to further discover exactly what is going wrong?
Advertisement
AFAIK it just encapsulates std::string (and adds ref counting)
Maybe it is related to the way you handle obj.Animation?
Can you show me how the SceneObject is registered? And especially the Animation property?


This does indeed look like a bug in AngelScript, and I will investigate this further.

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

Sure, here is some of the source code:
http://nalin.suckerfree.org/public/code/rha/

asEngine.h/cpp binds Engine to AngelScript, while asSceneObject.h/cpp binds the SceneObject (from CSceneObject.h.)

It is currently using Irrlicht's string class, as binding std::string via the scriptstdstring add-on wasn't working. asString.h/cpp is the code to bind it. irrString.h is the Irrlicht string class (just in case you need to see it.)

If you need anything else, just ask. I can give you the complete project if need be.

---

I just now tried removing the reference from "void set_Animation(const string &in)", so it would just be "const string", and it fixes the crash. But it goes back to one of my original problems where the script just stops executing once it hits that function.
I haven't been able to reproduce this problem.

I wrote the following code to test this:

class CMyObj{public:	CMyObj() { refCount = 1; }	void set_Text(const string &s)	{		assert( s == "Hello world!" );	}	void AddRef() { refCount++; }	void Release() { if( --refCount == 0 ) delete this; }	int refCount;};CMyObj *MyObj_factory() {	return new CMyObj;}bool Test2(){	bool fail = false;	COutStream out;	int r;	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);	RegisterStdString(engine);	engine->RegisterObjectType("CMyObj", 0, asOBJ_REF);	engine->RegisterObjectBehaviour("CMyObj", asBEHAVE_FACTORY, "CMyObj @f()", asFUNCTION(MyObj_factory), asCALL_CDECL);	engine->RegisterObjectBehaviour("CMyObj", asBEHAVE_ADDREF, "void f()", asMETHOD(CMyObj, AddRef), asCALL_THISCALL);	engine->RegisterObjectBehaviour("CMyObj", asBEHAVE_RELEASE, "void f()", asMETHOD(CMyObj, Release), asCALL_THISCALL);	engine->RegisterObjectMethod("CMyObj", "void set_Text(const string &in)", asMETHOD(CMyObj, set_Text), asCALL_THISCALL);	const char *string = 		"void main() { \n"		"  CMyObj @obj = @CMyObj(); \n"		"  obj.Text = 'Hello world!'; \n"		"} \n";	asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);	mod->AddScriptSection("string", string);	r = mod->Build();	if( r < 0 ) 		fail = true;	r = ExecuteString(engine, "main()", mod);	if( r != asEXECUTION_FINISHED )		fail = true;	engine->Release();	return fail;}


The CMyObj::set_Text property accessor is called with a proper string object.

I'm using MSVC++ 2008 Express and Windows 7 64bit to do these tests. What compiler and operative system are you using?

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

On Windows, I am using Visual C++ 2010 Beta 2.
On Linux, I am using g++ version 4.4.1.

I'm currently not at home right now, so I don't have access to a 64-bit Windows computer. I've attempted to walk through my issue on 64-bit Linux via gdb in an attempt to figure out why it is failing, but didn't succeed as I am still not very familiar with all of the inner workings of AngelScript. The result of that is here:
http://nalin.pastebin.com/m1dfb1e30

Here is a bytecode dump from my Linux build:
http://suckerfreegames.com/as/test.raw.lin64

It seems like AngelScript isn't storing/retrieving the string correctly, but I can't be too sure. When I get back home later on tonight, I'll work on getting you some code to reproduce it.
Well, I found the problem. It was related to this line:
r = engine->RegisterObjectMethod("GameEngine", "bool keydown(EKEY_CODE)",	asMETHOD(CGame, key_pressed), asCALL_THISCALL); assert(r >= 0);

Here is the code that defines EKEY_CODE:
http://sfg.pastebin.com/m47bc91f9

The full GameEngine bind can be found here:
http://nalin.suckerfree.org/public/code/rha/asEngine.cpp

This is the CGame::key_pressed function:
bool key_pressed(EKEY_CODE key){	if ((u32)key >= KEY_KEY_CODES_COUNT) return false;	return KeyState[(u32)key];}

I would call "keydown" in my script like so:
if (Engine.keydown(KEY_UP))	{ move.Y += 1.0f; dir = 0; domove = true; }

For some reason, AngelScript was choking on this use of enum when compiled as 64-bit code. To fix it, I changed the AngelScript "keydown" function to take a uint instead of an EKEY_CODE. I then bound it to this function:
bool Engine_keydown(unsigned int key, CGame& obj){	return obj.key_pressed((EKEY_CODE)key);}

AngelScript converts the enum to a uint and passes it to the function, which turns it back into an enum. It is now perfect and I don't crash anymore.
just FYI, you are registering key_pressed ( not Engine_keydown ) as keydown
Quote:Original post by slugear
just FYI, you are registering key_pressed ( not Engine_keydown ) as keydown

Yes, that is what I had BEFORE my fix.

Before fix:
r = engine->RegisterObjectMethod("GameEngine", "bool keydown(EKEY_CODE)",	asMETHOD(CGame, key_pressed), asCALL_THISCALL); assert(r >= 0);


After fix:
r = engine->RegisterObjectMethod("GameEngine", "bool keydown(uint)",	asFUNCTION(Engine_keydown), asCALL_CDECL_OBJLAST); assert(r >= 0);...bool Engine_keydown(unsigned int key, CGame& obj){	return obj.key_pressed((EKEY_CODE)key);}
Great, that narrows it down quite a bit. Thanks a lot for this update.



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