BIM Coordinator Program (INT) April 22, 2024

Find the next step in your career as a Graphisoft Certified BIM Coordinator!

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

ACAPI_LibPart_UpdateSection error

gehairing
Participant

Hello everyone,

 

It's a long time i didn't work on an Archicad add-on. It's a pleasure to be back .

 

I have upgraded  and enhanced older add-ons i had written for AC 18 to AC 22.

Now i have a problem i couldn't understand. I have searched & tried other things for days, so i think it's time to ask here. 🐵

 

I have an error using the ACAPI_LibPart_UpdateSection. It returns me an APIAPIERR_BADPARS error and i can't find out why. Below is a complete function i use for adding or updating one parameter of a given LibPart.

Everything run's well until the last call to UpdateSection.

 

I have tried simplifying the code, tried on several ten's of libparts, nothing changes. I have also tried a version where i only do getting the existing parameters and then try to reset exactly the same parameter via the UpdateSection and receive same error. 

 

The library files (.gsm) are copied in the API_SpecFolderID::API_EmbeddedProjectLibraryFolderID. The copies are correct and are usable normally in Archicad 25.

 

Did some essential things changed in the new API (AC25) ?

Do you see something wrong in this code ?

 

Thanks a lot,

 

Georges

 

The calling code (simplified) :

 

// Get the library part
GSErrCode err = ACAPI_LibPart_Get(&libPart);

... other code here

if (libPart.location != NULL)
{
    delete libPart.location;
    libPart.location = NULL;
}

... other code here

AddOrUpdateParameter(libPart, bacParameter);

 

The function with the problem at the end :

 

 

// Add or replace one parameter in given Library part
void BACDownload::AddOrUpdateParameter(API_LibPart& libPart, BACParameter bacParameter)
{
	GSErrCode err;

	API_AddParType parameter;

	// Manage type
	switch(bacParameter.typeCode)	
	{
	case BACObjectProperty::eDataType::kDTUndefined:
		// We use default string setting if type code is undefined
		SetStringValue(bacParameter.name, bacParameter.value, APIParT_CString, parameter);
		break;
	case BACObjectProperty::eDataType::kDTNumerical:
		SetRealValue(bacParameter.name, ""/*mappingEntry.unitCode*/, bacParameter.value, APIParT_RealNum, parameter);
		break;
	case BACObjectProperty::eDataType::kDTBoolean:
		break;
	case BACObjectProperty::eDataType::kDTString:
		SetStringValue(bacParameter.name, bacParameter.value, APIParT_CString, parameter);
		break;
	default:
		SetStringValue(bacParameter.name, bacParameter.value, APIParT_CString, parameter);
		break;
	};

	// Copy the description name 
	GS::ucscpy(parameter.uDescname, bacParameter.name.ToUStr());

	API_LibPartSection section;
	BNZeroMemory(&section, sizeof(API_LibPartSection));
	section.sectType = API_SectParamDef;

	// Get correct section
	GSHandle sectionHdl = NULL;
	err = ACAPI_LibPart_GetSection(libPart.index, &section, &sectionHdl, NULL);
	if (err) return;

	// Get current parameters
	double a, b;
	Int32 addParNum, i;
	API_AddParType **addPars;
	err = ACAPI_LibPart_GetParams(libPart.index, &a, &b, &addParNum, &addPars);
	if (err) return;

	bool existingParameter = false;

	// Does the parameter exist ?
	for (Int32 i = 0; i < addParNum; i++)
	{
		GS::UniString us = (*addPars)[i].name;
		if (CHCompareASCII((*addPars)[i].name, parameter.name) == 0)
		{
			GS::UniString s1 = (*addPars)[i].uDescname;
			GS::UniString s2 = parameter.uDescname;
			if (s1 == s2)
			{
				// Parameter already exist
				existingParameter = true;
			}
		}
	}

	if (existingParameter)
	{
		// Replace existing parameter

		// Create a new handle by allocating space for all existing parameters
		short nPars = addParNum;
		API_AddParType** newAddPars = reinterpret_cast<API_AddParType**>(BMAllocateHandle(nPars * sizeof(API_AddParType), ALLOCATE_CLEAR, 0));
		if (addPars != NULL)
		{
			// Copy all existing parameter and modify one
			for (i = 0; i < addParNum; i++)
			{

				// Is it the existing one ?
				if (CHCompareASCII((*addPars)[i].name, parameter.name) == 0)
				{
					// Replace it by the new one
					(*newAddPars)[i] = parameter;
				}
				else
				{
					// Recopy the same one
					(*newAddPars)[i] = (*addPars)[i];
				}
			}

			// Build a section handle with all parameters
			GSHandle Sect2DHdl = NULL;
			err = ACAPI_LibPart_GetSect_ParamDef(&libPart, newAddPars, &a, &b, NULL, &sectionHdl);

			BMKillHandle(reinterpret_cast<GSHandle*>(&newAddPars));
		}
	}
	else
	{
		// Add a new parameter

		// Create a new handle by allocating space for all parameters (existing ones and new ones)
		short nPars = addParNum + 1;
		API_AddParType** newAddPars = reinterpret_cast<API_AddParType**>(BMAllocateHandle(nPars * sizeof(API_AddParType), ALLOCATE_CLEAR, 0));
		if (addPars != NULL)
		{
			// Copy all existing parameters
			for (i = 0; i < addParNum; i++)
			{
				API_AddParType* parameter = &(*addPars)[i];
				(*newAddPars)[i] = (*addPars)[i];
			}

			(*newAddPars)[addParNum + 0] = parameter;

			// Build a section handle with all parameters
			GSHandle Sect2DHdl = NULL;
			err = ACAPI_LibPart_GetSect_ParamDef(&libPart, newAddPars, &a, &b, NULL, &sectionHdl);

			BMKillHandle(reinterpret_cast<GSHandle*>(&newAddPars));
		}
	}

	// Update our section
	err = ACAPI_LibPart_UpdateSection(libPart.index, &section, sectionHdl, NULL);
	// NOTE : Here above i get and error : APIERR_BADPARS :	-2130313112 : The passed parameters are inconsistent.

	BMKillHandle(&sectionHdl);
	ACAPI_DisposeAddParHdl(&addPars);
}

 

 

 

 

1 REPLY 1
gehairing
Participant

Hello

I have tried a simplified code like the one below here.
The error is exactly the same.

The solution is probably something very simple...but i can't see what 😉


// Experimental function for addPar updates
void BACDownload::TestParameterUpdates(API_LibPart& libPart)
{
	// Get the library part
	GSErrCode err = ACAPI_LibPart_Get(&libPart);
	if (err == NoError)
	{
		if (libPart.location != NULL)
		{
			delete libPart.location;
			libPart.location = NULL;
		}
	}

	// Define a parameter section
	API_LibPartSection section;
	BNZeroMemory(&section, sizeof(API_LibPartSection));
	section.sectType = API_SectParamDef;

	// Get parameter section
	GSHandle sectionHdl = NULL;
	err = ACAPI_LibPart_GetSection(libPart.index, &section, &sectionHdl, NULL);
	if (err) return;

	// Get current parameters
	double a, b;
	Int32 addParNum, i;
	API_AddParType** addPars;
	err = ACAPI_LibPart_GetParams(libPart.index, &a, &b, &addParNum, &addPars);
	if (err) return;
	
	// ..
	// Do nothing with the parameters
	// ..

	// Build a section handle with all parameters
	GSHandle Sect2DDrawHdl = NULL;
	err = ACAPI_LibPart_GetSect_ParamDef(&libPart, addPars, &a, &b, Sect2DDrawHdl, &sectionHdl);

	// Update our section
	err = ACAPI_LibPart_UpdateSection(libPart.index, &section, sectionHdl, NULL);
	// NOTE : Here above i get and error : APIERR_BADPARS :	-2130313112 : The passed parameters are inconsistent.

	BMKillHandle(&sectionHdl);
	ACAPI_DisposeAddParHdl(&addPars);
}

 

Learn and get certified!