Archicad C++ API
About Archicad add-on development using the C++ API.

Selecting SEO operators

Anonymous
Not applicable
Hi,

I'm trying to find and select all SEO operators. I'm fairly new to C++ and was wondering why this code doesn't work? The commented line crashes Archicad and I'm not sure why.
GS::GSErrCode err = NoError;
GS::Array<API_Guid> allElements;
		
ACAPI_Element_GetElemList(API_ZombieElemID, &allElements);

for (const API_Guid &guid : allElements) {

	GS::Array<GS::UniString> guidStrings;
	API_Guid **guid_Operators = nullptr;
	Int32 nLinks;
	err = ACAPI_Element_SolidLink_GetOperators(guid, &guid_Operators, &nLinks);

	BMhFree(reinterpret_cast<GSHandle> (guid_Operators));

	if (err != NoError)
		continue;

	GS::Guid nGuid = APIGuid2GSGuid (**guid_Operators); //crashes Archicad

	GS::UniString guidString = nGuid.ToUniString();
	guidStrings.Push(guidString);

	const USize count = guidStrings.GetSize();

	API_Neig** neigs = (API_Neig**)(BMAllocateHandle(count * sizeof(API_Neig), ALLOCATE_CLEAR, 0));
	for (UIndex i = 0; i < count; ++i) {
		(*neigs).guid = APIGuidFromString(guidStrings.ToCStr().Get());
	}

	ACAPI_Element_Select(neigs, count, true);
	BMKillHandle(reinterpret_cast<GSHandle*> (&neigs));

}

If anyone could help that would be great.

Thanks
3 REPLIES 3
Hello,

Can you explain here where do you put these C++ lines to be sure that everyone is able to understand ?
Christophe - FRANCE
Archicad Designer and Teacher
Archicad 15 to 27 FRA FULL

OS 11.6 Big Sur - MacBook Pro 2017 - 16Go RAM
"Quality is never an accident ; it's always the result of an intelligent effort" John Ruskin
Ralph Wessel
Mentor
It's because the data you want to inspect is destroyed in this line:
BMhFree(reinterpret_cast<GSHandle> (guid_Operators));
That instruction releases the memory used by that variable, so the data is no longer safe or meaningful, hence it crashes when you try to reference it in the following line:
GS::Guid nGuid = APIGuid2GSGuid (**guid_Operators);
Don't release the allocated memory until you're finished with it.
Ralph Wessel BArch
Anonymous
Not applicable
Thanks for the replies. Currently I'm using this code in a ButtonClicked function in a modal dialog box. I've managed to fix it so that it functions as required.
void Dialog::ButtonClicked(const DG::ButtonClickEvent& ev) {

	GS::GSErrCode err = NoError;
	GS::Array<API_Guid>	allElements;

	if (ev.GetSource() == &button)
		Text.SetText(CalculateCount());
	else if (ev.GetSource() == &sButton) {

		if (sButton.GetText() == "Select")

			Text.SetText("Please use the drop down menu to choose\nwhat to select");

		else if (sButton.GetText() == sButton.GetItemText(1)) {

			Text.SetText("Close this dialog to finish selection");

			ACAPI_Element_GetElemList(API_ZombieElemID, &allElements);

			for (const API_Guid& guid : allElements) {

				GS::Array<GS::UniString> guidStrings;
				API_Guid** guid_Operators = nullptr;
				Int32 nLinks = 0;
				err = ACAPI_Element_SolidLink_GetOperators(guid, &guid_Operators, &nLinks);

				if (err != NoError) {
					continue;
				}

				API_Neig** neigs = (API_Neig * *)(BMAllocateHandle(nLinks * sizeof(API_Neig), ALLOCATE_CLEAR, 0));
				for (int i = 0; i < nLinks; i++) {
					(*neigs).guid = guid_Operators[0];
				}

				ACAPI_Element_Select(neigs, nLinks, true);
				BMKillHandle(reinterpret_cast<GSHandle*> (&neigs));
				BMhFree(reinterpret_cast<GSHandle> (guid_Operators));

			}
		}
		else if (sButton.GetText() == sButton.GetItemText(2)) {

			Text.SetText("Close this dialog to finish selection");

			ACAPI_Element_GetElemList(API_ZombieElemID, &allElements);

			for (const API_Guid& guid : allElements) {

				GS::Array<GS::UniString> guidStrings;
				API_Guid** guid_Targets = nullptr;
				Int32 nLinks = 0;
				err = ACAPI_Element_SolidLink_GetTargets(guid, &guid_Targets, &nLinks);

				if (err != NoError) {
					continue;
				}

				API_Neig** neigs = (API_Neig * *)(BMAllocateHandle(nLinks * sizeof(API_Neig), ALLOCATE_CLEAR, 0));
				for (int i = 0; i < nLinks; i++) {
					(*neigs).guid = guid_Targets[0];
				}

				ACAPI_Element_Select(neigs, nLinks, true);
				BMKillHandle(reinterpret_cast<GSHandle*> (&neigs));
				BMhFree(reinterpret_cast<GSHandle> (guid_Targets));

			}
		}
	}
}

Cheers.