# API Conventions

## Type Definitions

The file A3DSDKTypes.h provides essential fixed-size numeric types used throughout the API:

Type | Description | Standard Type Equivalent
--- | --- | ---
`A3DBool` | Boolean descriptor. Can be `A3D_TRUE` or `A3D_FALSE` | `char`
`A3DUns8` | Unsigned integer type with width of exactly 8 bits | `unsigned char`
`A3DInt8` | Signed integer type with width of exactly 8 bits | `char`
`A3DUns16` | Unsigned integer type with width of exactly 16 bits | `unsigned short`
`A3DInt16` | Signed integer type with width of exactly 16 bits | `short`
`A3DInt32` | Signed integer type with width of exactly 32 bits | implementation dependent
`A3DUns32` | Unsigned integer type with width of exactly 32 bits | implementation dependent
`A3DDouble` | IEEE 754 64-bits floating-point number | `double`
`A3DFloat` | IEEE 754 32-bits floating-point number | `float`
`A3DVoid` | Void type Void type | `void`
`A3DPtr` | Void pointer type type Void pointer type type | `void*`
`A3DUTF8Char` | UTF-8 character type | `char*`

## Architecture

The HOOPS Exchange architecture is closely tied to its naming design. Most data in your HOOPS application are manipulated through entities, such as PRC, features, or BIM entities. Each entity type consists of:

- An enumerator value within `A3DEEntityType` used for identification.
- A handle type that uniquely identifies the entity within HOOPS.
- Optionally, a data structure for retrieving or editing the entity’s state.

Additionally, the API may provide CRUD-like functions for each entity type to manipulate its content. Not all entity types offer all functions, depending on relevance and indirect operations.

The following table illustrates the strict naming convention used for an entity type with some examples:

| Model File | BIM Data | NURBS Curve | Topo Body
--- | --- | --- | --- | ---
Handle Type | `A3DAsmModelFile` | `A3DBIMData` | `A3DCrvNurbs` | `A3DTopoBody`
`A3DEntityType` | `kA3DTypeAsmModelFile` | `kA3DTypeBIMData` | `kA3DTypeCrvNurbs` | `kA3DTypeTopoBody`
`struct` | `A3DAsmModelFileData` | `A3DBIMDataData` | `A3DCrvNurbsData` | `A3DTopoBodyData`
Create | `A3DAsmModelFileCreate()` |  | `A3DCrvNurbsCreate()` |
Get | `A3DAsmModelFileGet()` | `A3DBIMDataGet()` | `A3DCrvNurbsGet()` | `A3DTopoBodyGet()`
Set |  |  |  | `A3DTopoBodySet()`
Delete | `A3DAsmModelFileDelete()` |  |  |

### Querying the Entity Type of a Handle

When you have an entity handle and need to determine its underlying type, use `A3DEntityGetType` and match the result to `A3DEEntityType`. For example, to check if `pHandle` is a model file:

    A3DEEntityType eType = kA3DTypeUnknown;
    A3DEntityGetType(pHandle, &eType);
    assert(eType == kA3DTypeAsmModelFile);

### Retrieving the Data of an Entity

The most common operation on an entity is retrieving its data for reading. This involves initializing the data structure, retrieving the entity data, and disposing of the data structure when no longer needed. Here’s an example function that retrieves and prints the number of children product occurrences:

    void PrintChildrenPO(const A3DAsmProductOccurrence* pHandle)
    {
      A3DAsmProductOccurrenceData sData = A3D_MAKE_DATA(A3DAsmProductOccurrenceData);
      A3DAsmProductOccurrenceGet(pHandle, &sData);

      printf("Number of children: %d\n", pData->m_uiPOccurrencesSize);

      A3DAsmProductOccurrenceGet(0, &sData);
    }

Let’s detail this code line by line. To initialize a data structure, declare it as a non-const variable use the `A3D_MAKE_DATA` macro:

    A3DAsmProductOccurrenceData sData = A3D_MAKE_DATA(A3DAsmProductOccurrenceData); // don't use &

Once the structure is initialized, use the Get function to retrieve the data. In the following line, `pHandle` is of type `const A3DAsmProductOccurrence*`.

    A3DAsmProductOccurrenceGet(pHandle, &sData);

Then, when the data is not needed anymore, give the data back to the API by calling the same function. Set the handle parameter to 0.

    A3DAsmProductOccurrenceGet(0, &sData);

Note

Why disposing the data structure?

HOOPS Exchange structures may contains heap allocated data such as arrays and strings. It is essentials to remain memory consistent by letting the API releasing it. See the section about memory management for more.

### Arrays as `struct` Fields

Lists in HOOPS Exchange offer access to different data fields, like product occurrences in a model file or representation items in an `A3DRiSet`. To work with these lists, HOOPS Exchange uses standard C sequential array types. Each array is composed of two parts: an `A3DUns32` field to store the array’s size and a pointer to the array itself.

    typedef struct {
        // ...
        A3DUns32 m_uiPOccurrencesSize;
        A3DAsmProductOccurrences** m_ppOccurrences;
        // ...
    } A3DAsmModelFile;

Some array size specifiers can describe multiple arrays, illustrating their close relationship.

### Entity Hierarchy

The HOOPS architecture incorporates an abstraction and specialization mechanism for its entities. For instance, all entities can be abstracted as an `A3DEntity` type, while the majority of entities are specializations of `A3DRootBase`. In practical terms, this means that when an entity can be abstracted into another type, it can be safely manipulated as the abstract type..

Certain abstract types also have their own data structures. For example, any product occurrence represented as an `A3DAsmProductOccurrence` is also considered a root base entity, specifically an `A3DRootBase`. Therefore, the code remains valid even if `pHandle` is an instance of `A3DAsmProductOccurrence*`.

    A3DRootBaseData sData = A3D_MAKE_DATA(A3DRootBaseData);
    A3DRootBaseGet(pHandle, &sData);

Conversely, it’s possible to pass a handle of type `A3DRootBase*` to a function that anticipates an `A3DAsmProductOccurrence*`. In such cases, the responsibility falls upon the caller to ensure the entity’s correct type. For instance, this example verifies the type of `pHandle` before passing it to the `PrintChildrenPO` function, as shown in the previous example.

    A3DEEntityType eType = kA3DTypeUnknown;
    A3DEntityGetType(pHandle, &eType);

    if (eType == kA3DTypeAsmProductOccurrence) {
      PrintChildrenPO(pHandle);
    }

Any API call using an unexpected entity type will return `A3D_INVALID_ENTITY_TYPE`.

Note

Because it’s similar to but not exactly like object-oriented programming (OOP), the way entities are organized can be something confusing. Another way to understand the relationship between entity types is to think of HOOPS Exchange as a database. For instance, in this example, the term “pHandle” would be like a key that exists in both the “ProductOccurrence” and “A3DRootBase” tables.

#### Structural Hierarchy

Many complex structures in HOOPS Exchange are organized like trees. For instance, the PRC tree contains all the parts that make up a model file. And the Feature tree arranges all the steps a CAD application takes to create the final part. Within these structures, one entity instance can be the “parent” of one or more other entities.

Although there’s no direct connection between the structural and type hierarchies, it’s worth noting that entities in the same tree usually belong to the same entity type. For example, entities in a PRC tree can be things like `A3DAsmProductOccurrence,` `A3DRiRepresentationItem,` or `A3DRiPart` (and others), but they’re all types of `A3DRootBase.`

### Memory Management

Since HOOPS Exchange is a C API, you need to explicitly free any memory that’s allocated during runtime after you’re done using it. Many functions and data structures provide such memory, but it’s up to your application to decide when to release it.

One common scenario for memory cleanup is when you’re retrieving entity data, as shown in the example for entity data retrieval. If the Get function allocates memory, it’s important to note that these memory blocks are specific to that particular function call. For example, in the following case, `sData0.m_pcName` and `sData1.m_pcName` point to different memory locations, even though they belong to the same entity. This happens because the Name of a root base is copied into the A3DRootBaseData parameter internally.

    A3DRootBaseData sData0 = A3D_MAKE_DATA(A3DRootBaseData);
    A3DRootBaseData sData1 = A3D_MAKE_DATA(A3DRootBaseData);

    A3DRootBaseGet(pHandle, &sData0);
    A3DRootBaseGet(pHandle, &sData1);

    assert(sData0.m_pcName != sData1.m_pcName);

After you’ve finished using the code, you need to return both `sData0` and `sData1` to the library so that it can properly clean up the allocated memory. You can do this by making another call to `A3DRootBaseGet` with 0 as the handle.

    A3DRootBaseGet(0, &sData1);
    A3DRootBaseGet(0, &sData0);

Warning

Even if a data structure currently doesn’t use dynamically allocated memory, it might in future API versions. To ensure your code remains robust and avoids tricky memory leaks due to changes, it’s a good practice to always clean up your data structures, regardless of their type.

Certain functions also provide dynamically allocated memory using “out parameters” In these cases, you can find details on how to release that memory in the function’s documentation.

#### Providing the Memory Functions

If you want to control how memory is allocated within HOOPS API functions, you can set your own allocation and deallocation functions:

    A3DPtr CustomAlloc(size_t uiSize)
    {
      return malloc(uiSize);
    }

    A3DVoid CustomFree(A3DPtr pBlock) {
      free(pBlock);
    }

    A3DDllSetCallbacksMemory(CustomAlloc, CustomFree);

`A3DDllSetCallbacksMemory` must be called before `A3DDllInitialize`.

#### Deleting Entities

Deleting an entity itself isn’t a common operation in HOOPS Exchange, but some entity types do offer a delete function.

When you use `A3DModelFileDelete()` on a model file entity, it gets entirely removed. This action includes all the `A3DRootBase` entities that make up the PRC structure. Most of the time, this is the only delete function you need.

The more general-purpose `A3DEntityDelete()` function can be used to delete a specific entity. It removes the entity itself and any child entities in the case of an `A3DRootBase`. It’s important to note that this function doesn’t check whether the given entity exists somewhere in the PRC tree.

Some specific entities provide their own Delete() function:

- `A3DFaceUVPointInsideManagerDelete`
- `A3DFileContextDelete`
- `A3DMiscCascadedAttributesDelete`
- `A3DMkpRTFDelete`
- `A3DMkpRTFFieldDelete`
- `A3DProjectPointCloudManagerDelete`

#### Garbage Collection

When you shut down the library, the HOOPS context takes care of releasing any remaining memory blocks. This includes internal buffers and unlinked entities.

### Error Management

HOOPS manages errors by returning a status code from all its functions. If a function completes without errors, it returns the value `A3D_SUCCESS` (which is 0). Any non-zero value indicates an error.

You can find a comprehensive list of error codes in the `A3DStatus` enumeration within the A3DSDKErrorCodes.h file.

It’s important to note that the same error code might have different meanings depending on the function that returns it. For detailed information about a value returned by a specific function call, consult the documentation of that function.

`A3DMiscGetErrorMsg()` can be used to obtain a description of the error code:

    // ...
    A3DStatus iStatus = A3DAsmModelFileLoadFromFile(pcPath, &sLoadData, &pHandle);

    if (iStatus) {
      fprintf(stderr, "Cannot load model file: '%s'\n", A3DMiscGetErrorMsg(iStatus));
    }

### String Encoding

HOOPS uses standard C-Strings for handling text, which are in-memory arrays of characters with a null-termination character (0).

When dealing with character data, HOOPS Exchange adopts UTF-8 encoding. Therefore, any function or structure that needs strings as input must ensure proper conversion to UTF-8 before use. The API offers utility functions for these conversions:

- `A3DMiscUTF16ToUTF8`
- `A3DMiscUTF8ToUTF16`
- `A3DMiscUTF8ToUnicode`
- `A3DMiscUnicodeToUTF8`

## Code Conventions

HOOPS Exchange is a C API, which means any source code, including our headers, is assured to compile with a C or C++ compliant compiler. To get detailed information about the compiler requirements, you can refer to the platform requirements page.

### Header Files

All the header files can be found directly under the include/ folder of your HOOPS installation. These files are named using PascalCase and have one of the following prefixes:

- A3DSDK for most of our SDK.
- A3DPDF for files specific to the Advanced Publishing SDK.
- A3DCommon for code that is common to both APIs.

The only exception is hoops_license.h. This file should be replaced with the one typically obtained from the license file generator.

All our header files contain only the declarations and inclusions they need for compilation. They are also designed to be self-sufficient, meaning they don’t depend on the inclusion context to work correctly, as long as the `#include` directive is at the global scope.

To compile a source file using HOOPS declarations, you only need to include the relevant header file that contains the declaration you require. For example, including A3DSDKStructure.h is sufficient to compile a source code that uses the `A3DAsmModelFileData` structure.

If you want to include all API header files in one go, you can use the convenience header A3DSDKIncludes.h. This file is also included within A3DSDKLoader.h to ensure that all functions are loaded correctly during initialization.

### Naming Conventions

The API follows certain naming conventions:

- Symbol names are in PascalCase, with the exception of macro definitions and `A3DStatus` values, which use CAPITAL_CASE.
- Variables, formal parameters, and struct members use a naming convention known as Systems Hungarian Notation:
  - Struct members begin with `m_`, followed by:
  - `p` for pointer type, and then
  - A prefix based on the data type:
    - `b` for `A3DBool`
    - `i` for `A3DInt8`, `A3DInt16`, and `A3DInt32`
    - `ui` for `A3DUns8`, `A3DUns16`, and `A3DUns32`
    - `f` and `d` for `A3DFloat` and `A3DDouble`, respectively
    - `c` for `A3DUTF8Char`
    - `e` for enumerations
    - `s` for structures

### Namespacing

All data types and functions are organized using a series of prefixes.

The primary prefix is always `A3D`, and it’s followed by additional prefixes to create sub-namespaces for functions and related symbols.

For example, `A3DTess3DCreate()` and `A3DTessMarkupCreate()` share the same base name but belong to different sub-namespaces, namely `Tess3D` and `TessMarkup`, respectively.

Associated symbols also follow the same naming pattern:

- `A3DAsmModelFile`: This represents an entity handle for an assembly model file.
- `A3DAsmModelFileData`: This is a data structure that describes a model file.
- `A3DAsmModelFileLoadFromFile()`: This function is responsible for loading a model file into memory.

Conversation saved
HOOPSY BETA

### Hello! I'm HOOPSY

Your multilingual generative AI assistant for documentation. Ask me anything about HOOPS Exchange in your own language, or choose a sample question below to start a conversation:

What is HOOPS Exchange?
What are the latest release notes for HOOPS Exchange?
How do I start evaluating HOOPS Exchange?
How do I write my first sample application?
How can I get assistance?

HOOPSY may store conversations according to OpenAI's policy. Responses may not always be accurate.

HOOPSY is thinking...