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.

How to set values for array value in Object?

Tran Thanh Lo
Booster

HI guys, 

I have an object tool loaded into ArchiCAD and it has a parameter which is an array value. Now I want to get it and set a new value for it. 

I did it like this as in LibPart_Test:

UInt32 totalParams1 = BMGetHandleSize((GSConstHandle)memo.params);

	UInt32 totalParams = BMGetHandleSize((GSConstHandle)memo.params) / sizeof(API_AddParType);

	for (UInt32 i = 0; i < totalParams; i++) {

		if ((*memo.params)[i].name == (GS::UniString)"matrix_area")
		{
			(*memo.params)[i].value.array = BMAllocateHandle((*memo.params)[i].dim1 * (*memo.params)[i].dim2 * sizeof(double), ALLOCATE_CLEAR, 0);

			double** arrHdl = reinterpret_cast<double**>((*memo.params)[i].value.array);

			for (Int32 k = 0; k < (*memo.params)[i].dim1; k++)
				for (Int32 j = 0; j < (*memo.params)[i].dim2; j++)
					(*arrHdl)[k * (*memo.params)[i].dim2 + j] = (k == j ? 1.1 : 0.0);

		}
	}

But It's not right.

Can you help me know where I'm wrong?

Thank you very much.

3 REPLIES 3

Hi,

There could be a lot of different issues, depending mostly on where you get the memo from.
So please specify what you do before this code with the memo structure and also what specifically is not working.

 

One of my guesses is, that one of your dim1 or dim2 are maybe 0.

Best,

Bernd

Bernd Schwarzenbacher - Archicad Add-On Developer - Get Add-Ons & Archicad Tips on my Website: Archi-XT.com

Hi bschwb,

Thank you for responding, I get the memo like this. And my dim1 and dim2 have a value.

Can you help me tell me where I'm wrong?

 

API_Element element;
	API_ElementMemo memo;
	API_LibPart libPart;

	BNZeroMemory(&element, sizeof(API_Element));
	BNZeroMemory(&libPart, sizeof(API_LibPart));
	BNZeroMemory(&memo, sizeof(API_ElementMemo));
	BNClear(element);
	BNClear(memo);

	GSErrCode			err;

	BNZeroMemory(&libPart, sizeof(API_LibPart));

	libPart.typeID = APILib_ObjectID;

	CHCopyC("{4FD10D67-2F29-4844-A65A-6597589B0CB5}-{3BC96B79-9E97-42A3-969C-600334C0D18D}", libPart.parentUnID);
	GS::ucscpy(libPart.docu_UName, L("Schedule1"));

	err = ACAPI_LibPart_Search(&libPart, false);

	if (err == APIERR_BADNAME)
		ACAPI_WriteReport("Khong tim thay thu vien", false);

	element.header.type = API_ObjectID;
	err = ACAPI_Element_GetDefaults(&element, &memo);
	if (err != NoError) {
		ACAPI_WriteReport("ACAPI_Element_GetDefaults has failed with error code %ld!", true, err);
		ACAPI_DisposeElemMemoHdls(&memo);
		return;
	}

	double				aa = 0, bb = 0;
	Int32				addParNum;
	ACAPI_LibPart_GetParams(libPart.index, &aa, &bb, &addParNum, &memo.params);

	element.object.libInd = libPart.index;
	


	err = ACAPI_Goodies(APIAny_CloseParametersID);

And I change to this but it's still not right.

UInt32 totalParams1 = BMGetHandleSize((GSConstHandle)memo.params);


	UInt32 totalParams = BMGetHandleSize((GSConstHandle)memo.params) / sizeof(API_AddParType);

	int num_row = 8;
	int num_col = 4;
	for (UInt32 i = 0; i < totalParams; i++) {
		if ((*memo.params)[i].name == (GS::UniString)"matrix_area")
		{
			API_AddParType* pAddPar = &(*memo.params)[i];

			double** arrHdl = reinterpret_cast<double**>(pAddPar->value.array);
			for (Int32 k = 0; k < num_row; k++)
				for (Int32 j = 0; j < num_col; j++)
					(*arrHdl)[k * num_col + j] = 11;

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

 

There are a few issues with your code.

  1. I think ACAPI_Goodies (APIAny_CloseParametersID) is unnecessary here (because you don't use all of the other APIAny_OpenParametersID etc.) Better to leave it out if you don't do the other stuff as well.
  2. Don't kill the "arrHdl" handle after you just changed it! It references the data in the memo which you need to create the element.
  3. It's still not clear if the dimensions you want and the dimensions of the actual allocated array parameter match.

Here's your code changed so it creates an object if you have a library part with an existing parameter called "matrix_area".

I'm using references instead of handles and pointers in some places because it's easier for me to read.

 

void Create ()
{
	API_Element element;
	API_ElementMemo memo;
	API_LibPart libPart;

	BNZeroMemory (&element, sizeof (API_Element));
	BNZeroMemory (&libPart, sizeof (API_LibPart));
	BNZeroMemory (&memo, sizeof (API_ElementMemo));
	BNClear (element);
	BNClear (memo);

	GSErrCode err;

	libPart.typeID = APILib_ObjectID;

	GS::ucscpy (libPart.docu_UName, L ("test"));

	err = ACAPI_LibPart_Search (&libPart, false);

	if (err == APIERR_BADNAME) {
		ACAPI_WriteReport ("Khong tim thay thu vien", false);
	}

	element.header.type = API_ObjectID;
	err = ACAPI_Element_GetDefaults (&element, &memo);
	if (err != NoError) {
		ACAPI_WriteReport ("ACAPI_Element_GetDefaults has failed with error code %ld!", true, err);
		ACAPI_DisposeElemMemoHdls (&memo);
		return;
	}

	double				aa = 0, bb = 0;
	Int32				addParNum;
	ACAPI_LibPart_GetParams (libPart.index, &aa, &bb, &addParNum, &memo.params);
	element.object.libInd = libPart.index;

	UInt32 totalParams = BMGetHandleSize((GSConstHandle)memo.params) / sizeof(API_AddParType);

	int num_row = 8;
	int num_col = 4;
	for (UInt32 i = 0; i < totalParams; i++) {
		if ((*memo.params)[i].name == (GS::UniString)"matrix_area")
		{
			auto& currentParam = (*memo.params)[i];
			currentParam.dim1 = num_row;
			currentParam.dim2 = num_col;

			currentParam.value.array =
				BMReallocHandle (currentParam.value.array,
					num_row * num_col * sizeof (double),
					REALLOC_FULLCLEAR, 0);

			auto paramArray = reinterpret_cast<double*>(*currentParam.value.array);
			for (Int32 k = 0; k < num_row; k++)
				for (Int32 j = 0; j < num_col; j++)
					paramArray[k * num_col + j] = 11.0;

			// DON'T kill handle here already! We still need it to create the element!
			// It's just referenced through 'memo' there.
		}
	}

	err = ACAPI_Element_Create (&element, &memo);

	ACAPI_DisposeElemMemoHdls (&memo);
}

 

If you can't get it to work, please provide more details of what is not working specifically (error codes, expected vs. actual behavior or crashes).

Hope that helps!

Bernd

Bernd Schwarzenbacher - Archicad Add-On Developer - Get Add-Ons & Archicad Tips on my Website: Archi-XT.com
Learn and get certified!

Didn't find the answer?

Check other topics in this Forum

Back to Forum

Read the latest accepted solutions!

Accepted Solutions

Start a new conversation!