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.

Library Part - array - GSHandle

Anonymous
Not applicable
Hello there.

I have been trying to create library parts using the C++ API. However, I have encountered a problem when creating parameters for said library parts.

I can add parameters that are NOT arrays, using the different types (APIParT_Integer, etc...).

However, when I try to create parameters that are arrays, I do not seem to be handling the value.array correctly (GSHandle).

I'm trying to allocate memory for it, but my add-on keeps crashing.

Here is an excerpt of the code that is causing problems:
//...

(*addPars).typeMod = 2;

(*addPars).typeID = APIParT_Integer;
(*addPars).dim1 = 5;
(*addPars).dim2 = 1;

(*addPars).value.array = BMAllocateHandle(sizeof(GSHandle), ALLOCATE_CLEAR, 0);
*(*addPars).value.array = BMAllocatePtr(5 * sizeof(int), ALLOCATE_CLEAR, 0);

if ((*addPars).value.array == NULL || *(*addPars).value.array == NULL){
  ACAPI_WriteReport("NOPE!", true);
  return;
}

for (int j = 0; j < 5; j++){
  (int)((int *)*(*addPars).value.array) = msg.intarrays(intArrayCounter).lst(j);
}

//...
My question is how to correctly work with the array of the parameters.

Can someone help?

Thanks in advance,
Xylios
3 REPLIES 3
gehairing
Participant
Hi,

Did you look at the \Examples\LibPart_Test\Src\LibPart_Test.cpp in the SDK samples folder ?

There is an example for creating lib parts.

In the method "Do_CreateLibraryPart" there is a code for creating simple parameters and also array parameters.

Here is a part of the code but the best is to look at the complete sample :
			pAddPar = &(*addPars)[3];
			pAddPar->typeID = APIParT_RealNum;
			pAddPar->typeMod = API_ParArray;
			pAddPar->dim1 = 3;
			pAddPar->dim2 = 4;
			CHTruncate ("matrix", pAddPar->name, sizeof (pAddPar->name));
			GS::ucscpy (pAddPar->uDescname, L("Array parameter with real numbers"));
			pAddPar->value.array = BMAllocateHandle (pAddPar->dim1 * pAddPar->dim2 * sizeof (double), ALLOCATE_CLEAR, 0);
			double** arrHdl = reinterpret_cast<double**>(pAddPar->value.array);
			for (Int32 k = 0; k < pAddPar->dim1; k++)
				for (Int32 j = 0; j < pAddPar->dim2; j++)
					(*arrHdl)[k * pAddPar->dim2 + j] = (k == j ? 1.1 : 0.0);
Anonymous
Not applicable
Hey.

Thank you for the reply. I have looked at the LibPart_Test, but it was from the ArchiCAD 18 DevKit (the one I'm currently using) and it did not had the array example. I assume that the one you are using is the one from the ArchiCAD 19 DevKit.

I will try to get the one from the most recent DevKit, thank you.
Anonymous
Not applicable
Hey.

I have successfully created arrays of various types (such as APIParT_RealNum, APIParT_Integer ...) using the example you mentioned.

However, I have found another obstacle, I cannot seem to be able to create arrays of type string (APIParT_CString).

Anyone can help me with that?

I have tried to allocate space for char or double, and do the respective cast, but had no luck.
(*addPars).value.array = BMAllocateHandle(4 * sizeof(char), ALLOCATE_CLEAR, 0);
char** arrHdl = reinterpret_cast<char**>((*addPars).value.array);

//(*addPars).value.array = BMAllocateHandle(4 * sizeof(double), ALLOCATE_CLEAR, 0);
//double** arrHdl = reinterpret_cast<double**>((*addPars).value.array);

(*arrHdl)[0] = 'a';
(*arrHdl)[1] = '\0';
(*arrHdl)[2] = 'b';
(*arrHdl)[3] = '\0';

UPDATE:

I have found the solution:
//actualSize is the number of characters of every strings you want added plus the number of said strings
//ex: you want two strings "abc" and "st", the value of actualSize will be 3 + 2 + 2 = 7
//to note that the dim1 will still be the number of strings you want, in this example, 2. But you will allocate space for every character plus every separator '\0'.
//the final value of the array will be "abc\0st\0"
int numberOfStrings = 2;
(*addPars).dim1 = numberOfStrings;
(*addPars).dim2 = 1
(*addPars).value.array = BMAllocateHandle(actualSize * (*addPars).dim2 * sizeof(GS::uchar_t), ALLOCATE_CLEAR, 0);
GS::uchar_t** arrHdl = reinterpret_cast<GS::uchar_t**>((*addPars).value.array);
Hope that this can help anyone with the same problem.

Best regards,
Xylios
Learn and get certified!