Sign in to follow this  
_Sigma

Function parameters mushed up

Recommended Posts

Arg. Almost the same problem I was having here. I learnt from my mistake, and have gone over everything I can think of. The problem, to be clear, is that as soon as a function is called, all the parameters are all fuxed, and then the resulting code eventually dies a horrible death. This is the function I am calling. Just does a basic double buffered GDI call.
void TRenderer::RenderText( std::string text, int x, int y, COLORREF color)
{
	PAINTSTRUCT ps;
	HDC hdc;

	hdc = BeginPaint(m_hwnd, &ps); 


	HDC memDC = CreateCompatibleDC(hdc);
	HBITMAP hMemBmp = CreateCompatibleBitmap(hdc, m_screenWidth, m_screenHeight);
	HBITMAP hOldBmp = (HBITMAP)SelectObject(memDC, hMemBmp);
	LPCSTR ptr2 = text.c_str();

	SetBkMode(memDC, TRANSPARENT);
	SetTextColor(memDC, color);

	//make sure the number is no larger than  −2,147,483,648 to +2,147,483,647
	TextOut(memDC, x, y, ptr2, (int)(text.length()));

	// As a last step copy the memdc to the hdc
	BitBlt(hdc, 0, 0, m_screenWidth,m_screenHeight, memDC, 0, 0, SRCCOPY);

	EndPaint(m_hwnd, &ps);

	// Always select the old bitmap back into the device context
	SelectObject(memDC, hOldBmp);

	DeleteObject(hMemBmp);

	DeleteDC(memDC);


}

my fantastic AS test code:
#include "TKeyCodes.tscript"
				
		void main()
		{
		  
		  			  
			  
			  while(1==1)
			  {
			  
			  
					  if(Input.IsKeyDown(T_LEFT) == true)
					  {
					  	Screen.RenderText("Left key pressed!",30,30,65535);
					  }
					  
				  				   
				   //Return temporary control to the engine
				   //Without this call, the engine will hang.
				   Engine.Pause();
			   }
		  
		}

Function is registered like thus:
	m_script.RegisterObject("TRenderer");
	m_script.RegisterObjectMethod("TRenderer","void RenderText(const string& text, int x, int y, int color)",asMETHOD(TRenderer,RenderText));
	m_script.RegisterObjectMethod("TRenderer","int RGB(int8 r, int8 g, int8 b)",asMETHOD(TRenderer,BuildRGB));
	m_script.RegisterAsGlobal("TRenderer Screen",(void*)m_renderer);


here are the inner workings of these functions, but I'm 99.9% sure they work,a s I'm registering other functions just fine.
void TScript::RegisterObject( std::string declaration,int size/*=0*/,asDWORD flags/*=0*/ )
{
	int r = m_engine->RegisterObjectType(declaration.c_str(),size,flags);

	r < 0 ? throw TFatalException("Failed to register object" + declaration + " with Angel Script. \n\n In:\n TScript::RegisterObject") : ++r;
}

void TScript::RegisterObjectMethod( std::string obj, std::string declaration, asUPtr fnPtr)
{
	int r = m_engine->RegisterObjectMethod(obj.c_str(),declaration.c_str(),fnPtr,asCALL_THISCALL);
	
	r < 0 ? throw TFatalException("Failed to register object method " + declaration + " with Angel Script. \n\n In:\n TScript::RegisterObjectMethod") : ++r;
}

void TScript::RegisterAsGlobal( std::string declaration, void* ptr )
{
	if(ptr)
	{
		int r = m_engine->RegisterGlobalProperty(declaration.c_str(),ptr);
		r < 0 ? throw TFatalException("Failed to register global property" + declaration + " with Angel Script. \n\n In:\n TScript::RegisterGloalProperty") : ++r;
	}
	else
	{
		throw TFatalException("Failed to register global property " + declaration + " with Angel Script. Reason: Void function pointer. \n\n In:\n TScript::RegisterGloalProperty");
	}
}
void TScript::RegisterAsGlobal( std::string declaration, asUPtr fnPtr)
{
	int r = m_engine->RegisterGlobalFunction(declaration.c_str(), fnPtr ,asCALL_CDECL);

	r < 0 ? throw TFatalException("Failed to register function " + declaration + " with Angel Script. \n\n In:\n TScript::RegisterAsGlobal") : ++r;

}


m_renderer is a pointer. So I'm not making the same mistake as last time! m_renderer is initialized before the above code is called, and is valid (not null). I can call code on it from within c++ the this ptr doesn't seem to be screwed up at all. example of the strange parameters: Free Image Hosting at www.ImageShack.us any ideas?

Share this post


Link to post
Share on other sites
Registering a function that takes an std::string object by value is bad juju. Try using a string pointer or reference instead.

Share this post


Link to post
Share on other sites
I am a tool, hear me roar!

void TRenderer::RenderText( std::string text, int x, int y, COLORREF color)

m_script.RegisterObjectMethod("TRenderer","void RenderText(const string& text, int x, int y, int color)",asMETHOD(TRenderer,RenderText));

Oops....O_o

Andreas, perhaps AS shouldn't crash super hard when something like this happens?

Share this post


Link to post
Share on other sites
There's not much I can do about it. You're telling AngelScript to pass the parameters in one way, but the function is expecting something else. You're basically lying to AngelScript, and this is how the library is punishing you. ;)

This is a drawback of using the native calling conventions, mistakes like this will cause crashes that may be hard to detect. Other mistakes that cause similar problems is to register the types with the wrong flags, or the methods with the wrong calling conventions.

If you want to avoid horrible deaths you could wrap the Execute call with a try-catch. You still won't know very well what happened though. You're also likely to get corrupted memory so it may not be a good idea to continue the application after a crash like this.

Regards,
Andreas

Share this post


Link to post
Share on other sites
Quote:
Original post by WitchLord
There's not much I can do about it.
I feared as much!

Quote:
You're basically lying to AngelScript, and this is how the library is punishing you. ;)
And I though C was a harsh mistress!

Quote:
If you want to avoid horrible deaths you could wrap the Execute call with a try-catch.
Ah, what am I catching? I wasn't aware that the AS function threw exceptions...

Share this post


Link to post
Share on other sites
Actually, AngelScript doesn't throw any exceptions. You would be catching an OS exception, thrown when the code for the application function is called with the incorrect parameter and register values. It could be a memory access exception, or a stack alignment exception, or something else.


try
{
r = ctx->Execute();
}
catch(...)
{
// Gracefully exit the application
}


Note, that you'll only have this problem if you're configuring the engine incorrectly, so once you have a correct configuration there's no need to check for the exceptions.


Share this post


Link to post
Share on other sites
catch(...) will only catch things like access violations for some platforms. Actually, the only ones I can think of are the Windows based ones, since C++ exceptions are based on structured exception handling, which is used to report access violations. Posix based platforms will pop a signal like SIGSEGV. Some platforms will just crash without a chance to detect or recover.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this