The Global ARCHICAD Community

Stay informed. Get help. Share your knowledge.

Discussions about using GRAPHISOFT's tools (API DevKit) for independent software developers

Moderators: Karl Ottenstein, LaszloNagy, ejrolon, Barry Kelly, gkmethy, rmasaki, MOREH Tamas, Akos Somorjai, Ed Brown, Mihály Palenik, Tibor Lorántfy


Continuing on from my Reserve Library issue we are now able to programatically extract our GDL from the LCF and import it into the Embedded Library. The problem we're now encountering is that the textures/surfaces defined in the GDL are not immediately available in ARCHICAD. Specifically if I go into Attributes/Surfaces the surfaces are not listed. However, if I save and reload the file then the surfaces do appear. Additionally, if I manually load the GDL into the Emedded Library via the UI then the surfaces do immediately appear. I am assuming that the script isn't being executed when I copy and register it programatically but it is executed when the file is opened, or manually loaded in.

This is problematic as the next step we perform after loading the GDL to define the surfaces is create building materials that reference them. This fails since the surfaces are not available.

Note this issue has nothing to do with teamwork, it happens even with normal solo files.

The GDLs in question are master scripts from the LCF. In fact they are the only items in the LCF as all we need to do is define the textures/surfaces and it was easier in our pipeline to make LCFs like this than programatically create surfaces. I've have attached a sample GDL that shows the issue. The code we use to import is as follows:
Code: Select all

/// @param path the path on the filesystem to the GDL to import
/// @param library_folder path within the embedded library to import the item to
GS::Int32 Archlog_import::add_to_embedded_library(const IO::Location &path, const IO::RelativeLocation &library_folder)
	if (path.IsEmpty()) {
		return -2;

	GS::Array<API_LibraryInfo>    activeLibs;
	GSErrCode            err;
	GS::Int32 embeddedLibraryIndex = -1;

	err = ACAPI_Environment(APIEnv_GetLibrariesID, &activeLibs, &embeddedLibraryIndex);
	if (err != NoError || embeddedLibraryIndex == -1) {
		// no embedded library
		return -4;

	IO::Location embedded_folder = activeLibs[embeddedLibraryIndex].location;	
	IO::RelativeLocation folders(IO::Name("Arch-LOG"));

	for (USize i = 0; i < folders.GetLength(); ++i) {
		IO::Name folder;
		folders.GetName(i, &folder);
		err = ACAPI_Environment(APIEnv_CreateFolderInLibraryID, &embedded_folder);
		if (err != NoError) {
			return -5;
	GS::Array<IO::Location> fileToCopy;
	bool overwrite=true;
	err = ACAPI_Environment(APIEnv_CopyFilesIntoLibraryID, &embedded_folder, &fileToCopy, &overwrite);
	if (err != NoError) {
		return -6;
	IO::Location embedded_file(embedded_folder);
	IO::Name name;

	API_LibPart libPart;
	BNZeroMemory(&libPart, sizeof(API_LibPart));
	libPart.typeID = APILib_ObjectID;
	libPart.location = &embedded_file;
	err = ACAPI_LibPart_Register(&libPart);
	return err == NoError ? 0 : -7;
Is there some additional step we need to take to get the script to execute? Note that setting the part typeID to macro doesn't help.


(380 Bytes) Downloaded 2 times
I haven't tested this, but you might be able to get the desired result by doing something that makes the script run, e.g. modifying the default tool settings by changing a parameter. You can do this with APIAny_ChangeAParameterID (and set the target object as the default for the tool).
Forgive me for chiming in here as I know nothing about API development.
But is it possible to force a re-load of the embedded library?

OK, we've found that we can get it to run the script by doing a APIEnv_GetLibrariesID followed by a APIEnv_SetLibrariesID with the same list. However this doesn't work in Teamwork mode since we can't programatically reserve the library list (as noted in my Reserve Library thread).

Is there any other way we can for the script to be executed?