We value your input! Please participate in Archicad 28 Home Screen and Tooltips/Quick Tutorials survey
2021-09-28 12:02 PM - last edited on 2021-10-05 08:49 PM by Laszlo Nagy
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(§ion, sizeof(API_LibPartSection));
section.sectType = API_SectParamDef;
// Get correct section
GSHandle sectionHdl = NULL;
err = ACAPI_LibPart_GetSection(libPart.index, §ion, §ionHdl, 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, §ionHdl);
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, §ionHdl);
BMKillHandle(reinterpret_cast<GSHandle*>(&newAddPars));
}
}
// Update our section
err = ACAPI_LibPart_UpdateSection(libPart.index, §ion, sectionHdl, NULL);
// NOTE : Here above i get and error : APIERR_BADPARS : -2130313112 : The passed parameters are inconsistent.
BMKillHandle(§ionHdl);
ACAPI_DisposeAddParHdl(&addPars);
}
2021-10-04 08:13 AM
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(§ion, sizeof(API_LibPartSection));
section.sectType = API_SectParamDef;
// Get parameter section
GSHandle sectionHdl = NULL;
err = ACAPI_LibPart_GetSection(libPart.index, §ion, §ionHdl, 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, §ionHdl);
// Update our section
err = ACAPI_LibPart_UpdateSection(libPart.index, §ion, sectionHdl, NULL);
// NOTE : Here above i get and error : APIERR_BADPARS : -2130313112 : The passed parameters are inconsistent.
BMKillHandle(§ionHdl);
ACAPI_DisposeAddParHdl(&addPars);
}