omni::core::Api< omni::core::ITypeFactory_abi >

Defined in omni/core/ITypeFactory.h

template<>
class Api<omni::core::ITypeFactory_abi> : public omni::core::Generated<omni::core::ITypeFactory_abi>

Implements the generated API layer for omni::core::ITypeFactory

Public Functions

template<typename T>
inline ObjectPtr<T> createType(const char *moduleName = nullptr, uint32_t version = 0) noexcept

Instantiates an implementation of interface T.

See omni::core::ITypeFactory_abi::createType_abi() for instantiation rules.

template<typename T = IObject>
inline ObjectPtr<T> createType(TypeId id, const char *moduleName = nullptr, uint32_t version = 0) noexcept

Instantiates the given type and casts it to T.

The given type id can be an implementation id.

If the interface type T is not implemented by the type id, nullptr is returned.

See omni::core::ITypeFactory_abi::createType_abi() for instantiation rules.

inline omni::core::Result registerInterfaceImplementationsFromModule(const char *moduleName, omni::core::TypeFactoryLoadFlags flags) noexcept

Registers types from the given module.

If the module is currently loaded, it will not be reloaded and kResultSuccess is returned.

Modules (e.g. .dll or .so) may contain one or many implementations of one or many interfaces. When registering a module with the type factory, a function, whose name is described by ‘kModuleGetExportsName’, is found and invoked. Let’s assume the exported function name is “omniModuleGetExports”.

“omniModuleGetExports” returns a key/value database of the module’s capabilities and the module’s requirements. Some things to note about this database:

  • The module’s requirements can be marked as optional.

  • The module’s capabilities can be ignored by ITypeFactory.

These properties allow ITypeFactory and the module to find an intersection of desired functionality in a data driven manner. If one party’s required needs are not met, the module fails to load (e.g. an appropriate omni::core::Result is returned).

It is expected the module has entries in the key/value database describing the functions ITypeFactory should call during the loading process. The most important of these entries is the one defined by OMNI_MODULE_ON_MODULE_LOAD(), which points to the function ITypeFactory should call to get a list of implementations in the module. ITypeFactory invokes exports from the module in the following pattern:

.------------------------------------------------------------------------------------------------------------.
|                                               -> Time ->                                                   |
|------------------------------------------------------------------------------------------------------------|
| omniModuleGetExports | onLoad (req.) | onStarted (optional) | onCanUnload (optional) | onUnload (optional) |
|                      |               | impl1->createFn      |                        |                     |
|                      |               | impl2->createFn      |                        |                     |
|                      |               | impl1->createFn      |                        |                     |
\------------------------------------------------------------------------------------------------------------/

Above, functions in the same column can be called concurrently. It’s up to the module to make sure such call patterns are thread safe within the module.

onCanUnload and createFn can be called multiple times. All other functions are called once during the lifecycle of a module.

The module can be explicitly unloaded with unregisterInterfaceImplementationsFromModule().

See also

omni/core/ModuleExports.h.

See also

onModuleLoadFn

See also

onModuleStartedFn

See also

onModuleCanUnloadFn

See also

onModuleUnloadFn

Upon destruction of this ITypeFactory, unregisterInterfaceImplementationsFromModule is called for each loaded module. If the ITypeFactory destructor’s call to unregisterInterfaceImplementationsFromModule fails to safely unload a module (via the module’s onModuleCanUnload and onModuleUnload), an attempt will be made to forcefully/unsafely unload the module.

The given module name must not be nullptr.

This method is thread safe. Modules can be loaded in parallel.

Returns

Returns kResultSuccess if the module is loaded (either due to this function or a previous call). Otherwise, an error is returned.

inline omni::core::Result unregisterInterfaceImplementationsFromModule(const char *moduleName) noexcept

Unregisters all types registered from the given module.

Unregistering a module may fail if the module does not belief it can safely be unloaded. This is determined by OMNI_MODULE_ON_MODULE_CAN_UNLOAD().

If unregistration does succeed, the given module will be unloaded from the process space.

Upon destruction of this ITypeFactory, unregisterInterfaceImplementationsFromModule is called for each loaded module. If the ITypeFactory destructor’s call to unregisterInterfaceImplementationsFromModule fails to safely unload a module (via the module’s onModuleCanUnload and onModuleUnload), an attempt will be made to forcefully/unsafely unload the module.

The given module name must not be nullptr.

This method is thread safe.

Returns

Returns kResultSuccess if the module wasn’t already loaded or if this method successfully unloaded the module. Return an error code otherwise.

inline void registerInterfaceImplementations(const omni::core::InterfaceImplementation *implementations, uint32_t implementationsCount, omni::core::TypeFactoryLoadFlags flags) noexcept

Register the list of types.

Needed data from the “implementations” list is copied by this method.

This method is thread safe.

inline const char *getTypeIdName(omni::core::TypeId id) noexcept

Maps a type id back to its type name.

The memory returned is valid for the lifetime of ITypeFactory

Returns nullptr if id has never been registered. Types that have been registered, and then unregistered, will still have a valid string returned from this method.

This method is thread safe.

inline void setInterfaceDefaults(omni::core::TypeId interfaceId, omni::core::TypeId implId, const char *moduleName, uint32_t implVersion) noexcept

Sets the implementation matching constraints for the given interface id.

See omni::core::ITypeFactory_abi::createType_abi() for how these constraints are used.

moduleName can be nullptr.

if implVersion is 0 and implId is an implementation id, the implementation with the highest version is chosen.

This method is thread safe.

inline omni::core::Result getInterfaceDefaults(omni::core::TypeId interfaceId, omni::core::TypeId *outImplId, char *outModuleName, uint32_t *inOutModuleNameCount, uint32_t *outImplVersion) noexcept

Returns the implementation matching constraints for the given interface id.

See omni::core::ITypeFactory_abi::createType_abi() for how these constraints are used.

If the given output implementation id pointer (outImplid) is not nullptr, it will be populated with the default implementation id instantiated when the interface requested to be created.

If the given output implementation version pointer (outImplVersion) is not nullptr, it will be populated with the default implementation version instantiated when the interface is requested to be created.

If the output module name pointer (outModuleName) is not nullptr, it will be populated with the name of the module searched when trying to find an implementation of the interface. If there is no current default module name, the output module name will be populated with the empty string. If the output module name’s buffer size is insufficient to store the null terminated module name, kResultBufferInsufficient is returned and the module name’s buffer size is updated with the needed buffer size.

If the output module name is nullptr, the output module name buffer size (inOutModuleNameCount) will be populated with the size of the buffer needed to store the module name.

The output module name buffer size pointer (inOutModuleNameCount) must not be nullptr.

If the given interface id is not found, kResultNotFound is returned and the output implementation id (outImplId) and version (outImplVersion), if defined, are set to 0. Additionally, the output module name (outModuleName), if defined, is set to the empty string.

If kResultInsufficientBuffer and kResultNotFound are both flagged internally, kResultNotFound is returned.

See omni::core::getInterfaceDefaults() for a C++ wrapper to this method.

This method is thread safe.

inline void *cast(omni::core::TypeId id) noexcept

Returns a pointer to the interface defined by the given type id if this object implements the type id’s interface.

Objects can support multiple interfaces, even interfaces that are in different inheritance chains.

The returned object will have omni::core::IObject::acquire() called on it before it is returned, meaning it is up to the caller to call omni::core::IObject::release() on the returned pointer.

The returned pointer can be safely reinterpret_cast<> to the type id’s C++ class. For example, “omni.windowing.IWindow” can be cast to omni::windowing::IWindow.

Do not directly use this method, rather use a wrapper function like omni::core::cast() or omni::core::ObjectPtr::as().

Thread Safety

This method is thread safe.

inline void acquire() noexcept

Increments the object’s reference count.

Objects may have multiple reference counts (e.g. one per interface implemented). As such, it is important that you call omni::core::IObject::release() on the same pointer from which you called omni::core::IObject::acquire().

Do not directly use this method, rather use omni::core::ObjectPtr, which will manage calling omni::core::IObject::acquire() and omni::core::IObject::release() for you.

Thread Safety

This method is thread safe.

inline void release() noexcept

Decrements the objects reference count.

Most implementations will destroy the object if the reference count reaches 0 (though this is not a requirement).

Objects may have multiple reference counts (e.g. one per interface implemented). As such, it is important that you call omni::core::IObject::release() on the same pointer from which you called omni::core::IObject::acquire().

Do not directly use this method, rather use omni::core::ObjectPtr, which will manage calling omni::core::IObject::acquire() and omni::core::IObject::release() for you.

Thread Safety

This method is thread safe.

Protected Functions

virtual IObject *createType_abi(TypeId id, const char *moduleName, uint32_t implVersion) noexcept = 0

Instantiates a concrete type.

The given type id can be an interface or implementation id.

If the id is an interface id, the following rules are followed:

  • If the application specified a default implementation, that implementation will be instantiated.

  • Otherwise, the first registered implementation of the interface is instantiated. If multiple versions of the implementation exist, the highest version is picked.

  • implVersion must be 0 since interfaces are not versioned (only implementations are versioned). If implVersion is not 0, nullptr is returned.

  • If a default module name was provided by the app, the rules above will only be applied to implementations from the specified default module.

If the id is an implementation id, the followings rules apply:

  • If version is 0, the highest version of the implementation is returned.

  • If version is not 0, the returned object is the specified version of the implementation. If such a version does not exists, nullptr is returned. If multiple implementations exists with the same version, the implementation registered first is instantiated.

In both cases above, if moduleName given, the rules above are followed by only looking at implementations from the specified module. If no match is found, nullptr is returned.

If moduleName has not been loaded, it will be loaded and its implementations registered.

If moduleName is nullptr, the rules above are applied across all loaded modules.

This method is thread safe.

virtual Result registerInterfaceImplementationsFromModule_abi(const char *moduleName, TypeFactoryLoadFlags flags) noexcept = 0

Registers types from the given module.

If the module is currently loaded, it will not be reloaded and kResultSuccess is returned.

Modules (e.g. .dll or .so) may contain one or many implementations of one or many interfaces. When registering a module with the type factory, a function, whose name is described by ‘kModuleGetExportsName’, is found and invoked. Let’s assume the exported function name is “omniModuleGetExports”.

“omniModuleGetExports” returns a key/value database of the module’s capabilities and the module’s requirements. Some things to note about this database:

  • The module’s requirements can be marked as optional.

  • The module’s capabilities can be ignored by ITypeFactory.

These properties allow ITypeFactory and the module to find an intersection of desired functionality in a data driven manner. If one party’s required needs are not met, the module fails to load (e.g. an appropriate omni::core::Result is returned).

It is expected the module has entries in the key/value database describing the functions ITypeFactory should call during the loading process. The most important of these entries is the one defined by OMNI_MODULE_ON_MODULE_LOAD(), which points to the function ITypeFactory should call to get a list of implementations in the module. ITypeFactory invokes exports from the module in the following pattern:

.------------------------------------------------------------------------------------------------------------.
|                                               -> Time ->                                                   |
|------------------------------------------------------------------------------------------------------------|
| omniModuleGetExports | onLoad (req.) | onStarted (optional) | onCanUnload (optional) | onUnload (optional) |
|                      |               | impl1->createFn      |                        |                     |
|                      |               | impl2->createFn      |                        |                     |
|                      |               | impl1->createFn      |                        |                     |
\------------------------------------------------------------------------------------------------------------/

Above, functions in the same column can be called concurrently. It’s up to the module to make sure such call patterns are thread safe within the module.

onCanUnload and createFn can be called multiple times. All other functions are called once during the lifecycle of a module.

The module can be explicitly unloaded with unregisterInterfaceImplementationsFromModule().

See also

omni/core/ModuleExports.h.

See also

onModuleLoadFn

See also

onModuleStartedFn

See also

onModuleCanUnloadFn

See also

onModuleUnloadFn

Upon destruction of this ITypeFactory, unregisterInterfaceImplementationsFromModule is called for each loaded module. If the ITypeFactory destructor’s call to unregisterInterfaceImplementationsFromModule fails to safely unload a module (via the module’s onModuleCanUnload and onModuleUnload), an attempt will be made to forcefully/unsafely unload the module.

The given module name must not be nullptr.

This method is thread safe. Modules can be loaded in parallel.

Returns

Returns kResultSuccess if the module is loaded (either due to this function or a previous call). Otherwise, an error is returned.

virtual Result unregisterInterfaceImplementationsFromModule_abi(const char *moduleName) noexcept = 0

Unregisters all types registered from the given module.

Unregistering a module may fail if the module does not belief it can safely be unloaded. This is determined by OMNI_MODULE_ON_MODULE_CAN_UNLOAD().

If unregistration does succeed, the given module will be unloaded from the process space.

Upon destruction of this ITypeFactory, unregisterInterfaceImplementationsFromModule is called for each loaded module. If the ITypeFactory destructor’s call to unregisterInterfaceImplementationsFromModule fails to safely unload a module (via the module’s onModuleCanUnload and onModuleUnload), an attempt will be made to forcefully/unsafely unload the module.

The given module name must not be nullptr.

This method is thread safe.

Returns

Returns kResultSuccess if the module wasn’t already loaded or if this method successfully unloaded the module. Return an error code otherwise.

virtual void registerInterfaceImplementations_abi(const InterfaceImplementation *implementations, uint32_t implementationsCount, TypeFactoryLoadFlags flags) noexcept = 0

Register the list of types.

Needed data from the “implementations” list is copied by this method.

This method is thread safe.

virtual const char *getTypeIdName_abi(TypeId id) noexcept = 0

Maps a type id back to its type name.

The memory returned is valid for the lifetime of ITypeFactory

Returns nullptr if id has never been registered. Types that have been registered, and then unregistered, will still have a valid string returned from this method.

This method is thread safe.

virtual void setInterfaceDefaults_abi(TypeId interfaceId, TypeId implId, const char *moduleName, uint32_t implVersion) noexcept = 0

Sets the implementation matching constraints for the given interface id.

See omni::core::ITypeFactory_abi::createType_abi() for how these constraints are used.

moduleName can be nullptr.

if implVersion is 0 and implId is an implementation id, the implementation with the highest version is chosen.

This method is thread safe.

virtual Result getInterfaceDefaults_abi(TypeId interfaceId, TypeId *outImplId, char *outModuleName, uint32_t *inOutModuleNameCount, uint32_t *outImplVersion) noexcept = 0

Returns the implementation matching constraints for the given interface id.

See omni::core::ITypeFactory_abi::createType_abi() for how these constraints are used.

If the given output implementation id pointer (outImplid) is not nullptr, it will be populated with the default implementation id instantiated when the interface requested to be created.

If the given output implementation version pointer (outImplVersion) is not nullptr, it will be populated with the default implementation version instantiated when the interface is requested to be created.

If the output module name pointer (outModuleName) is not nullptr, it will be populated with the name of the module searched when trying to find an implementation of the interface. If there is no current default module name, the output module name will be populated with the empty string. If the output module name’s buffer size is insufficient to store the null terminated module name, kResultBufferInsufficient is returned and the module name’s buffer size is updated with the needed buffer size.

If the output module name is nullptr, the output module name buffer size (inOutModuleNameCount) will be populated with the size of the buffer needed to store the module name.

The output module name buffer size pointer (inOutModuleNameCount) must not be nullptr.

If the given interface id is not found, kResultNotFound is returned and the output implementation id (outImplId) and version (outImplVersion), if defined, are set to 0. Additionally, the output module name (outModuleName), if defined, is set to the empty string.

If kResultInsufficientBuffer and kResultNotFound are both flagged internally, kResultNotFound is returned.

See omni::core::getInterfaceDefaults() for a C++ wrapper to this method.

This method is thread safe.

virtual void *cast_abi(TypeId id) noexcept = 0

Returns a pointer to the interface defined by the given type id if this object implements the type id’s interface.

Objects can support multiple interfaces, even interfaces that are in different inheritance chains.

The returned object will have omni::core::IObject::acquire() called on it before it is returned, meaning it is up to the caller to call omni::core::IObject::release() on the returned pointer.

The returned pointer can be safely reinterpret_cast<> to the type id’s C++ class. For example, “omni.windowing.IWindow” can be cast to omni::windowing::IWindow.

Do not directly use this method, rather use a wrapper function like omni::core::cast() or omni::core::ObjectPtr::as().

Thread Safety

This method is thread safe.

virtual void acquire_abi() noexcept = 0

Increments the object’s reference count.

Objects may have multiple reference counts (e.g. one per interface implemented). As such, it is important that you call omni::core::IObject::release() on the same pointer from which you called omni::core::IObject::acquire().

Do not directly use this method, rather use omni::core::ObjectPtr, which will manage calling omni::core::IObject::acquire() and omni::core::IObject::release() for you.

Thread Safety

This method is thread safe.

virtual void release_abi() noexcept = 0

Decrements the objects reference count.

Most implementations will destroy the object if the reference count reaches 0 (though this is not a requirement).

Objects may have multiple reference counts (e.g. one per interface implemented). As such, it is important that you call omni::core::IObject::release() on the same pointer from which you called omni::core::IObject::acquire().

Do not directly use this method, rather use omni::core::ObjectPtr, which will manage calling omni::core::IObject::acquire() and omni::core::IObject::release() for you.

Thread Safety

This method is thread safe.