Initializing HOOPS Exchange

HOOPS Exchange is a C API provided using a set of header files and binaries. These binaries are A3DLIBS.dll for Windows (MSVC), A3DLIBS.so for Linux and Android, and A3DLIBS.dylib for macOS. The only exception is iOS where HOOPS Exchange is provided as a static library. The archive object is then A3DLIBS.a.

In C there are two ways of loading a shared library. Either by linking against it when building your application or by manually loading it and getting its functions using system calls such as LoadLibrary with Windows or dlopen with GNU compilers. The latter is called explicit load and is how HOOPS Exchange is used.

Because HOOPS Exchange is a shared library, functionality is exposed using function pointers that have to be initialized once for every application. This is the purpose of the loading and initializing step.

Once you are finished using Exchange, the shared object must be uninitialized and unloaded; this is the terminating and unloading step.

General

This section presents a step-by-step example of how to initialize HOOPS Exchange. For the full example, you can skip to the next section.

Initializing HOOPS Exchange is a two step process. First the client application is set up then the loaded DLL is initialized to ask Exchange to set up its internal data.

Setting up the client application must be done once per process. Upon loading, the client application loads the Exchange library and sets all function pointers to a valid address. This step is called loading.

Then the HOOPS Exchange library must be initialized by calling one of the previously loaded functions. This step must be done once per shared object. This step is called initializing.

Disposing HOOPS Exchange is the reverse process where the DLL is optionally terminated (if it was previously initialized) then unloaded. These steps are called terminating and unloading HOOPS Exchange.

Include Exchange Headers

As with other libraries, the Exchange API is declared using header files (extension: .h). One of them is used to include all the APIs: A3DSDKIncludes.h. Including A3DSDKIncludes.h is the recommended approach.

The INITIALIZE_A3D_API macro is used to allow initialization of the library. See the section below for more information about this macro.

#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>

Linux and macOS users, please note: HOOPS Exchange uses dynamic loading during its execution. If you are using HOOPS Exchange on a Linux or macOS platform, you must configure your compiler for this requirement. This means defining the HAVE_DLFCN_H preprocessor flag and linking against DLFCN using the -ldl linker option.

Loading the Library

When you load the library, you instruct the system to load the shared object file and set all function pointers to their respective values. This is done by calling A3DSDKLoadLibrary(). This function exists in two versions :

  • Use A3DSDKLoadLibraryA() if you wish to specify the library path using const char*.

  • Use A3DSDKLoadLibraryW() if you wish to specify the library path using const wchar_t*.

Note

In A3DSDKLoader.h, the A3DSDKLoadLibrary() function is defined as a macro that expands to the wide character version if the macro _UNICODE was previously set. If _UNICODE is not set, then the A3DSDKLoadLibrary() function expands to the const char* form.

In any case, the value of the sole parameter for A3DSDKLoadLibrary() is the path to the folder containing the shared library: A3DLIBS.dll on Windows, A3DLIBS.so on Linux and Android, or A3DLIBS.dylib on macOS.

Warning

Calling A3DSDKLoadLibrary() is only available if the macro INITIALIZE_A3D_API is set prior to the include statement for A3DSDKIncludes.h.

A3DBool loaded = A3DSDKLoadLibraryA(PATH_TO_A3DLIBS_DIR);

if(loaded)
{
  // HOOPS Exchange Loaded
}

Providing the License

Now that all the functions are loaded, the very first function to call is A3DLicPutUnifiedLicense().

This function provides the license to the library, which is required for any other calls to the API.

A3DStatus result = A3DLicPutUnifiedLicense(HOOPS_LICENSE);

if(result == A3D_SUCCESS)
{
  // License provided
}

HOOPS_LICENSE is a convenience macro provided by hoops_license.h. It expands to your license key.

The license file must be available from a direct #include statement such as:

#include <hoops_license.h>

The simplest way to make this file available is to drop it into the include folder of your HOOPS Exchange installation.

If any call to the API is done without a valid license set first, the function returns A3D_INVALID_LICENSE. This error code is also returned by A3DLicPutUnifiedLicense() when given an invalid license key.

Initializing the Library

Initializing the library is a library-side operation where HOOPS Exchange performs some internal initializations.

To initialize the library, call A3DDllInitialize(). The expected parameter values are the major and minor version number of the API to initialize. By default you can use A3D_DLL_MAJORVERSION and A3D_DLL_MINORVERSION to specify the same version as your header files. This function returns A3D_SUCCESS if everything went well.

A3DStatus result = A3DDllInitialize(A3D_DLL_MAJORVERSION, A3D_DLL_MINORVERSION);

if(result == A3D_SUCCESS)
{
  // HOOPS Exchange initialized
}

Initializing is done once. If several programs load the same HOOPS Exchange binaries, the initialization is shared.

As a convenience, HOOPS Exchange provides a function to check if the library has already been initialized: A3DDllIsInitialized().

Terminating the Library

When your application is finished with HOOPS Exchange, the library must be notified so that it can dispose any used resources, which is accomplished by calling ref PFA3DDllTerminate() “A3DDllTerminate”. Just as with A3DDllInitialize(), A3DDllTerminate() must be called once per application, and every call to A3DDllInitialize() should be paired with a call to A3DDllTerminate().

A3DDllTerminate();

As a general rule, the process that initialized HOOPS Exchange and the one that terminates it should be the same.

Unloading the Library

Unloading the library is a client-side operation where all function pointers are reset to 0 and the library file is unloaded. The function to call is A3DSDKUnloadLibrary() and it is a client-side operation.

A3DSDKUnloadLibrary();

Note

Calling A3DSDKUnloadLibrary is only available if the macro INITIALIZE_A3D_API is set prior to include A3DSDKIncludes.h.

Code Example

The code below is a minimal yet complete working example that illustrates how to initialize HOOPS Exchange from any C client application.

#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>

int main(int argc, char* argv[])
{
  // Load the library
  A3DBool loaded = A3DSDKLoadLibraryA(PATH_TO_A3DLIBS_DIR);
  assert(loaded);

  // We are responsible for calling 'initialize' and 'terminate' if the
  // library is not already initialized
  A3DBool must_initialize = !A3DDllIsInitialized();

  if(must_initialize) {
    A3DStatus result = A3DLicPutUnifiedLicense(HOOPS_LICENSE);
    assert(result == A3D_SUCCESS);

    result = A3DDllInitialize(A3D_DLL_MAJORVERSION, A3D_DLL_MINORVERSION);
    assert(result == A3D_SUCCESS);
  }

  // HOOPS Exchange ready to use!

  if(must_initialize) {
    A3DDllTerminate();
  }

  // Unload the library
  A3DSDKUnloadLibrary();

  return EXIT_SUCCESS;
}

Compiling this code requires minimal configuration - simply add the HOOPS Exchange include folder to your compiler.

The INITIALIZE_A3D_API Macro

A3DSDKLoadLibrary() and A3DSDKUnloadLibrary() are not available by default. If you want to call them, you must define INITIALIZE_A3D_API prior to include A3DSDKIncludes.h.

This macro:

  • Provides A3DSDKLoadLibrary() and A3DSDKUnloadLibrary().

  • Defines all function pointers (without the INITIALIZE_A3D_API, they would be declared but not defined).

In your application, it is important that one source file only defines the INITIALIZE_A3D_API macro. The function pointers will be defined in this compilation unit - hence, using INITIALIZE_A3D_API in more than one source file will end up generating multiple-definition errors.

Alternatively it is possible to include A3DSDKLoader.h instead of both defining INITIALIZE_A3D_API and including A3DSDKIncludes.h.The same “one compilation unit rule” applies to including A3DSDKLoader.h (i.e., only do it in one source file in your application).

Special Rules

HOOPS Exchange provides an extension library called the HOOPS Parasolid Bridge . This library is able to translate models back and forth between HOOPS Exchange and a Parasolid session. For more information, see HOOPS Exchange for Parasolid Developers.

On iOS, HOOPS Exchange is provided as a static library . Therefore, functions related to the Parasolid Bridge are statically linked in the application, regardless of whether you use them or not. By default the Parasolid Bridge is considered as not used. All functions are then replaced with placeholders to avoid linker issues with your compiler.

When you want to use HOOPS Exchange along with the Parasolid Bridge, you must define an additional macro along with INITIALIZE_A3D_API: A3DAPI_NO_IOS_HEPB_STUB. This will remove the placeholder functions from your build and avoid double definitions upon linking with libhepb.a:

#define INITIALIZE_A3D_API
#define A3DAPI_NO_IOS_HEPB_STUB
#include <A3DSDKIncludes.h>

// HOOPS Exchange Initialization

This restriction is only applicable to iOS builds since this is the only platform where Parasolid is statically linked.

The HOOPSExchangeLoader Class

If your client application uses C++, you may use the HOOPSExchangeLoader class. This simple structure brings C++ RAII principle into the HOOPS Exchange loading operation.

During the lifetime of a HOOPSExchangeLoader instance, HOOPS Exchange is guaranteed to be initialized. Once the instance goes out of scope the library is automatically disposed. Thus, any call to HOOPS Exchange function must be done within the lifetime of the HOOPSExchangeLoader instance.

#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>

void use_hoops_exchange()
{
  HOOPSExchangeLoader loader(PATH_TO_A3DLIBS_DIR);
  // HOOPS Exchange loaded and initialized

  if(loader.m_eSDKStatus == A3D_SUCCESS)
  {
    // HOOPS Exchange ready to use!
  }

  return EXIT_SUCCESS;
  // HOOPS Exchange uninitialized and unloaded
}