Advertisement

Possible bug in function call order

Started by March 06, 2009 10:30 AM
2 comments, last by WitchLord 15 years, 8 months ago
I have the following code: main.cpp cstring.h cstring.cpp When I run the following script:
int scriptmain( int argc )
{
	cstring s = "test";
	print( s );
	
	return argc;
}
I get the expected output:
CONSTRUCT
FACTORY( 0x259ed00 'test' )
COPY( 0x259ed00 )
DESTRUCT( 0x259ed00 )
CONV( 0x259ed20 'test' )
SCRIPT SAYS (0x259ed20):
test
DESTRUCT( 0x259ed20 )
The script function returned: 0
However, if I change the script to look like this:
int scriptmain( int argc )
{
	print( "test" );
	
	return argc;
}
this is the (incorrect) output I get:
FACTORY( 0x982d00 'test' )
CONV( 0x982d00 'test' )
DESTRUCT( 0x982d00 )
SCRIPT SAYS (0x982d00):

The script function returned: 0
Is this a result of an error in my code or is there a deeper problem with the order in which AS calls functions in the second case ? (note how the 'destructor' is called before the call to the printing function)
AngelScript is behaving as expected.

Your cstring type has an implicit value cast to int64. AngelScript has no way of knowing that the value returned by the cast actually is the string, so it thinks it is safe to destroy the cstring value after the cast.

The fact that example 1 works and not example 2 is because in example 1 the cstring is a local variable, so it will only be destroyed when it goes out of scope. In example 2 the cstring is a temporary variable which is destroyed as soon as it is no longer needed.

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

Advertisement
I understand. Guess my problem is: how do I register functions which take 'char *' as parameters ? The problem is that with the current implementation passing 'cstring' by value is not possible on x86_64 platforms because AS considers that 'cstring' is an 'object type' which can't be passed be value (an exception is thrown in as_callfunc_x64_gcc.cpp in PrepareSystemFunction()). Obviously there is the possibility of writing wrapper functions which use CScriptString but that really isn't practical for cases (like mine) where there are a lot of functions which would require wrappers. The whole idea behind the implicit conversion to int64 in my example was to work around the current limitation. I thought that by registering the type with asOBJ_APP_PRIMITIVE flag set AS would treat it as one of the 'standard' types but it turned out I was wrong.
You should indeed register the cstring as asOBJ_APP_PRIMITIVE, however it doesn't change how AngelScript handles the object within the compiler/VM, it is only for the native calling convention support. as_callfunc_x64_gcc.cpp should use this flag to understand how to pass the type by value to the application functions.

However, even after fixing the as_callfunc_x64_gcc.cpp code to properly handle the registered char pointer, you'll still have to manually treat the deallocation of the string buffer. With cstring AngelScript will allocate a string buffer when passing the string to a function, it is the responsibility of the function to deallocate that string buffer when it is finished with it.

Trying to use functions that take or return char* with AngelScript (and most likely any other script language) will be difficult. I really recommend that you implement wrapper functions for these, and instead use either the std::string or CScriptString as the AngelScript string type.

You can possibly implement template functions for automatic generation of these wrapper functions, that way you don't have to implement and maintain them manually.

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