Hello, world! (C++)

This is the C++ counterpart of the Python Hello, world! crash course. It guides you through the same basic code snippets, but using the IfcOpenShell C++ API, and shows the direct C++ equivalent of each Python operation.

See also

Every snippet on this page lives in its own .cpp file under docs/ifcopenshell/hello_world, and each of them is compiled and run as part of the documentation’s test suite. See Building and running the examples to build and run them yourself.

The examples use the IFC4 schema, so that the generated Ifc4 classes can be used by name, such as Ifc4::IfcWall. The C++ core is not tied to a single schema though, see Schema-agnostic parsing of IFCs for how to write the same logic in a way that processes all schema versions at once.

Note

Each example takes the path of the model as its first command line argument, and the snippets in this page assume that it has been loaded into a variable called model, exactly like the Python crash course assumes.

Loading the model

The equivalent of Python’s ifcopenshell.open() is the ifcopenshell::file constructor. A file that could not be read reports as not good, which is how you check that parsing succeeded.

Inspecting the schema

Getting an instance by ID

Every instance in an IFC-SPF file has a STEP ID, such as #1.

Getting an instance by GlobalId

Getting data from beginning to end is not too meaningful to humans, but a GlobalId is.

Counting the instances of a type

instances_by_type() returns all instances of an entity type, including subtypes, so IfcWallStandardCase instances are returned for IfcWall as well.

The class of an instance

Once we have an instance we can ask it what it is.

You can also test against other classes, including parent classes.

The STEP ID of an instance

Reading attributes

IFC attributes have a particular order, and can be addressed by their position just like a list.

Knowing the order of attributes is boring and technical, so the generated classes also have accessors named after the attribute, which are strongly typed and which wrap optional attributes in a std::optional.

Printing everything an instance holds

The C++ API does not return a dictionary of all attributes, but every instance can print itself as it appears in the IFC file, which is the equivalent of Python’s get_info().

Reading the property sets of an instance

Python has ifcopenshell.util.element.get_psets(), but the C++ core does not ship a ready made property set helper, so the relationships are walked by hand.

Inverse attributes

Some attributes are special, and are called “inverse attributes”. They happen when another instance is referencing our instance, for example to define a relationship. Just treat them like regular attributes.

Perhaps we want to see all instances which are referencing our instance, regardless of which attribute they use to do so.

Traversing references

The opposite of the previous example: everything our instance references.

Modifying data

To modify data, assign it to the relevant attribute.

You can also generate a new GlobalId.

Writing the model

After modifying some IFC data, you can save it to a new IFC-SPF file.

Creating a new file

You can generate a new IFC file from scratch too, instead of reading an existing one. Such a file is in memory only until it is written out.

Creating instances

You can create new IFC instances, and they are added to the file that created them straight away.

Alternatively, you can also create an instance from the name of the entity as it appears in the IFC schema, which is the equivalent of Python’s create_entity().

Attributes can be filled in straight away, by their position, in the order of the attributes.

Again, knowing the order of attributes is difficult, so attributes can also be assigned by name.

Sometimes it is easier to collect the attributes in a table first, and assign them in a loop. This is the equivalent of expanding a Python dictionary into create_entity().

Some attributes of an instance are not text, but a reference to another instance. The generated setters take the referenced instance directly.

Copying an instance into another file

What if we already have an instance in one file, and want to add it to another? The forward references of the instance are copied along with it, and the copy is created in the schema of the target file, so both files have to use the same one.

Note that, unlike Python’s ifcopenshell.util.element.copy(), this does copy references recursively, but it makes no other attempts at resulting in a valid file, for example it does not convert length units between the two files.

Removing an instance

Fed up with an instance? Remove it.

Building and running the examples

The sources next to this page are a standalone CMake project which consumes an installed IfcOpenShell through find_package(IfcOpenShell CONFIG), the same way any other third party consumer would:

cd docs/ifcopenshell/hello_world
cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/ifcopenshell
cmake --build build --config RelWithDebInfo

Every example is registered as a test which runs it with hello_world.ifc, a small IFC4 model that ships with the examples:

ctest --test-dir build -C RelWithDebInfo --output-on-failure

There is also a single custom command which builds and runs all of them at once, and which fails if any of the examples reports a failure:

cmake --build build --config RelWithDebInfo --target run_examples

This is only a small sample of the basic building blocks of working with IFC data in C++. See getting_started for more on parsing, and the Geometry processing pages for turning this data into geometry.