ODA IFC SDK Developer's Guide > Get Started with IFC SDK > Create Your First IFC SDK Application
Create Your First IFC SDK Application

Prerequisites

This document describes the basic workflow of creating your first console application with IFC SDK.

Before creating, building, and running the application, download and unpack the following archives:

  • Kernel SDK.
  • IFC SDK.

To get detailed information about downloading the IFC SDK archives and choosing an appropriate archive for your platform, please see the Download ODA IFC SDK topic.

If you use trial archive versions, you also need to activate the appropriate ODA products. To get details about obtaining, deploying, and activating trial versions, please see ODA Trial Version Getting Started Guide.

It is assumed that the application source code file will be placed in the Ifc/Examples/ExIfcFirstApp folder.

The first application provides the following functionality:

  • Opens a specified .ifc file and loads its content.
  • Dumps the information about entities that are contained in the opened file to the console window.

Creating Your First Application

  1. Create a new console application project using your favorite IDE on your platform.
  2. Add a new source code file (ExIfcFirstApp.cpp) to the project. You can save this file in the Ifc/Examples/ExIfcFirstApp folder.
  3. Add include directives for the IFC SDK header files to the ExIfcFirstApp.cpp file:
    
    //System includes
    #include <iostream>
    #include <cstdlib>
     //IFC SDK includes
    #include <IfcExamplesCommon.h>
    #include <IfcCore.h>
    #include <OdaCommon.h>
    #include <StaticRxObject.h>
    #include <RxDynamicModule.h>
     #include <ExPrintConsole.h>
     #include <daiHeaderSection.h>
    #include <daiHeaderEntities.h>
            
  4. Add export declarations of initialization and de-initialization functions of the database functionality to the ExIfcFirstApp.cpp file:
    
    DBROOT_EXPORT void odDbRootInitialize();
    DBROOT_EXPORT void odDbRootUninitialize();
            
  5. Define enumeration values that the application returns:
    
    enum AppResult
    {
      arOk = 0,
      arIncorrectUsage,
      arFileOpenError,
      arEmptySectionHeader,
      arInvalidSchema,
      arUnsupportedSchema,
      arEmptyModel,
      arOdError,
      arUnexpectedError
    };
            
  6. Add the main() function definition to the ExIfcFirstApp.cpp file:
    
    int main(int argc, char* argv[])
    {
      setlocale(LC_TIME, ""); // set current user locale (not OD_T("C")), for strftime
       OdStaticRxObject <MyServices> svcs;
       odrxInitialize(&svcs);
       odDbRootInitialize();
       odIfcInitialize(false);
       svcs.disableProgressMeterOutput(true);
       odPrintConsoleString(L"\nIFC SDK First Application. Copyright (c) 2020, Open Design Alliance\n");
      odPrintConsoleString(L"\nExIfcFirstApp application developed using %ls ver %ls", svcs.product().c_str(), svcs.versionString().c_str());
       if (argc != 2)
      {
        odPrintConsoleString(L"\n\nusage: ExIfcFirstApp ");
        odPrintConsoleString(L"\n a full path to the input IFC file\n Press any key to finish...");
        getchar();
        return arIncorrectUsage;
      }
            
    
    odIfcUninitialize();
    odDbRootUninitialize();
    ::odrxUninitialize();
    return arOk;
    }
            

    The initial version of the main() function contains:

    • Creation of a custom services object. A custom services object is an instance of the MyServices class that is defined in the IfcExamplesCommon.h header file located in the Ifc/Examples/Common folder. For additional information, please see ODA IFC SDK Sample Applications Reusable Files.
    • ODA Software initialization by calling the following functions:
      • odrxInitialize()
      • odDbRootInitialize()
      • odIfcInitialize()
    • Printing of the information string about your first application and the IFC SDK version.
    • Checking the number of arguments passed to the application.
    • ODA Software de-initialization.
  7. Since the services class is inherited from the ExSystemServices and OdExIfcHostAppServices classes, add the following header and source files to your project:
    • Ifc/Extensions/ExServices/ExIfcHostAppServices.h
    • Ifc/Extensions/ExServices/ExIfcHostAppServices.cpp
    • Kernel/Extensions/ExServices/ExSystemServices.h
    • KernelBase/Extensions/ExServices/ExSystemServices.cpp

    One more source file should be added to the project to provide ODA Software memory management: KernelBase/Extensions/alloc/OdAllocOp.cpp.

  8. Add the source code to the main block and handling exceptions section:
    
    {
      OdIfcFilePtr pDatabase;
      try
      {
            
    
    }
    catch (OdError& e)
    {
      odPrintConsoleString(L"\nError occurred: %ls! Press any key to finish...", e.description().c_str());
      pDatabase = NULL;
      return arOdError;
    }
    catch (...)
    {
      odPrintConsoleString(L"\n\nUnexpected error.");
      pDatabase = NULL;
      return arUnexpectedError;
    }
    }
            
  9. Add a code fragment that reads data from a specified file and creates an instance of the OdIfcFile class in the try {} section:
    
    OdString ifcFileName(argv[1]);
    pDatabase = svcs.createDatabase(InitialSchema::kScmUndefined);
    OdResult res = pDatabase->readFile(ifcFileName);
    if (res == eOk)
    {
      odPrintConsoleString(L"\nFile opened successfully (%s).", ifcFileName.c_str());
    }
    else
    {
      odPrintConsoleString(L"\nFile open error (error code: %d). Press any key to finish...", res);
      getchar();
      pDatabase = NULL;
      return arFileOpenError;
    }
            
  10. Create and initialize the .ifc file header section and schema objects:
    
    //get header section
    OdDAI::OdHeaderSectionPtr headerSection = pDatabase->getHeaderSection();
    if (!headerSection.isNull())
    {
      //get and check the schema
      OdDAI::ApplicationInstancePtr fileSchema = headerSection->getEntityByType(OdDAI::kFileSchema);
      OdArray<OdAnsiString> schemas;
      if (fileSchema->getAttrCaseInsensitive("schema_identifiers") >> schemas)
      {
        for (const auto& schemaName : schemas)
        {
          OdDAI::SchemaPtr schema = oddaiGetSchema(schemaName);
          if (schema.isNull())
          {
            odPrintConsoleString(L"\nUnsupported schema %hs. Press any key to finish...", schemaName.c_str());
            getchar();
            pDatabase = NULL;
            return arUnsupportedSchema;
          }
          odPrintConsoleString(L"\nIFC File schema: %hs\n", schemaName.c_str());
        }
      }
    }
    else 
    {
      odPrintConsoleString(L"\nError getting header section from the %s file! Press any key to finish...", ifcFileName.c_str());
      getchar();
      pDatabase = NULL;
      return arEmptySectionHeader;
    }
            
  11. Retrieve the model object from the .ifc file and processes the error situation when the model is empty:
    
    OdIfc::OdIfcEntityPtr  pInst;
    OdIfcModelPtr          pModel = pDatabase->getModel();
    if (pModel.isNull())
    {
      odPrintConsoleString(L"\nAn unexpected error occurred while opening the IFC file! Press any key to finish...");
      getchar();
      pDatabase = NULL;
      return arEmptyModel;
    }
    odPrintConsoleString(L"Model entities: \n");
            
  12. Create an iterator for sequential access to the entities contained in the .ifc file, walk through the entities, and print information about each entity into the console window:
    
    OdDAI::InstanceIteratorPtr it = pModel->newIterator();
    unsigned int entIdx;
    for (entIdx = 0; !it->done(); it->step(), ++entIdx)
    {
      //opens an entity
      pInst = it->id().openObject();
      pInst = it->id().openObject();
      if (!pInst.isNull())
      {
        odPrintConsoleString(L"Entity %d: \n", entIdx);
        odPrintConsoleString(L"\tEntity handle (corresponds to the STEP-id) = %d\n", it->id().getHandle());
        odPrintConsoleString(L"\tEntity type code = %d\n", pInst->type());
        odPrintConsoleString(L"\tEntity type name = %hs\n", pInst->typeName().c_str());
        if (pInst->isKindOf(OdIfc::kIfcRepresentationItem) || pInst->isKindOf(OdIfc::kIfcProfileDef))
          odPrintConsoleString(L"\tEntity is kind of kGeom\n");
        else
          odPrintConsoleString(L"\tEntity is kind of kBIM\n");
      }
    }
    odPrintConsoleString(L"Found entities: %d\n", entIdx);
    //Finalize the process, OdIfcFile and underlying header section and Model will be released.
    pDatabase = NULL;
            

    After finishing the cycle with dumping entities' information to the console window, the program prints the total quantity of entities and destroys the .ifc file, header section, and model objects by assigning the NULL value to the IFC database smart pointer.

  13. Set the application project properties:
    • The path to the output directory where the application binary file will be created.

      For example, if you use Microsoft® Visual Studio® 2019 for 64-bit Windows® dynamic configuration, you can set the following path for the output directory in the project properties window: ..\..\..\..\..\exe\vc16_amd64dll\. It is assumed that the project for this configuration is allocated in the CMakePlatforms\vc15_amd64dll\Ifc\Examples\ExIfcFirstApp sub-directory of the IFC SDK installation folder.

    • Add the following folders to the project's include directories list:
      • KernelBase
      • KernelBase/Include
      • Kernel/Include
      • Kernel/Extensions/ExServices
      • Ifc/Include
      • Ifc/Include/Common
      • Ifc/Include/sdai
      • Ifc/Include/sdai/daiHeader
      • Ifc/Extensions/ExServices
      • Ifc/Examples/Common
      • ThirdParty
      • ThirdParty/activation

      These options are needed for your compiler to find ODA Software header files. Do not forget to add a relative path for each directory if needed to let the compiler find header files used in the project.

    • Add preprocessor definitions for your project:
      • UNICODE
      • TEIGHA_TRIAL
      • ODA_LICENSING_ENABLED
      • IFC_DYNAMIC_BUILD
      • _TOOLKIT_IN_DLL_
      • CMAKE_INTDIR="Release"

      The TEIGHA_TRIAL definition should be added only if you are using the IFC SDK trial version. If using the full version, place the OdActivationInfo file into the ThirdParty\activation directory.

      Please see Activating ODA Products for details about getting the activation file.

    • Add the path to the necessary libraries' location. These paths are required by the linker to find the ODA Software libraries the project depends on.

      For example, if you use Microsoft® Visual Studio® 2019 for 64-bit Windows® dynamic configuration, set the following paths for the library directories in the project properties window:

      • ..\..\..\..\..\exe\vc16_amd64dll
      • ..\..\..\..\..\lib\vc16_amd64dll

      It is assumed that the project for this configuration is allocated in the CMakePlatforms\vc15_amd64dll\Ifc\Examples\ExIfcFirstApp sub-directory of the IFC SDK installation folder.

    • Add the list of libraries, which should be linked with your application to the project:
      • IfcCore.lib
      • sdai.lib
      • TD_Gi.lib
      • TD_Ge.lib
      • TD_Root.lib
      • TD_DbRoot.lib
      • TD_DbRoot.lib
      • TD_ExamplesCommon.lib
      • TD_Alloc.lib
  14. Build and run your project.

    If the first application experiences errors, most likely you are using a trial archive that was not correctly activated. Please see ODA Software Trial Version Getting Started Guide due to get additional information about activating ODA Software trials.

    If your application successfully runs, it prints its output to the console.

You also can get the full source code of this first IFC SDK application.

See Also

Usage of IFC SDK Sample Applications

Library Dependencies of IFC SDK

Copyright © 2002 – 2020. Open Design Alliance. All rights reserved.