Common Pitfalls

From GMAPI

Jump to: navigation, search

This page lists the common pitfalls experienced when using GMAPI:

Contents

String Comparison

When comparing gm::CGMVariable with a blank string, you must use:

if (string == NULL)

instead of:

if (string == "")

The probable cause of this is how Delphi (the language Game Maker was created in) handles its strings.

Function Calling with gm::CGMVariable arguments

When calling functions with gm::CGMVariables passed as arguments, you must make sure that you pass the variables as references otherwise you will get segmentation faults caused by faulty deallocation at the end of your functions.

A correct function definition would be:

void controlClass::drawTitle(gm::CGMVariable &text)

Assignment of CGMVariable with &CGMVariable

The following code may look completely fine:

bool myFunc(gm::CGMVariable &request)
{
	gm::CGMVariable base = request;
	return false;
}

but it will in fact cause a segmentation fault higher up the function call chain. In this case, base is being assigned a reference to request, however, at the end of this function call, base will be deallocated. When base is deallocated, it is actually deallocating the request variable as well that was passed to the function because base is a reference to request, not a copy of it.

To copy a referenced CGMVariable, you should use .c_str() on the variable and assign that to the new CGMVariable. This will force the DLL to convert the referenced data into a non-referenced C-string and then assign it to the new variable.

Cloning a CGMVariable

gm::CGMVariable apiInterface::rg_highscore_get_rank(gm::CGMVariable username, gm::CGMVariable highscoreID)
{
	gm::CGMVariable didstart;

	if (!username.IsString())
		username = gm::CGMVariable(this->control->Login);

The code above is unsafe due to line 6. While it does not cause any visible compilation errors, it will cause memory corruption of the cloned variable (this->control->Login) when line 6 executes. As above, you should always use .c_str() and .real() to copy the value of CGMVariables. The correct line 6 would look like (since we want username to be assigned a string):

username = gm::CGMVariable(this->control->Login.c_str());

Likewise, the following code will also cause memory corruption and is especially dangerous if the returned value is going to be passed into GM (you will get memory corruption occurring inside the game runner - not in your DLL):

gm::CGMVariable apiInterface::rg_highscore_fetch_rank()
{
	return gm::CGMVariable(this->control->Highscore_GetRankValue);
}

The correct code is:

gm::CGMVariable apiInterface::rg_highscore_fetch_rank()
{
	return gm::CGMVariable(this->control->Highscore_GetRankValue.real());
}

Accessing CGMVariable in the DllMain entry point function

While trying to access CGMVariable class object in the DllMain entry point function when DLL_PROCESS_DETACH event occurs, you may get an access violation exception. The cause of this is that the Delphi's garbage collector in the runner frees all previously allocated strings on exit. To avoid this, the DLL must be freed by using external_free() before the game ends.

Personal tools