omni::core::ITypeFactory_abi

Defined in omni/core/ITypeFactory.h

class ITypeFactory_abi : public omni::core::Inherits<omni::core::IObject, std::integral_constant<uint64_t, carb::fnv1aHash("omni.core.ITypeFactory")>::value>

A mapping from type id’s to implementations.

This object maps type id’s to concrete implementations. The type id’s can represent interface ids or implementation ids.

Register types with registerInterfaceImplementationsFromModule() and registerInterfaceImplementations().

Instantiate types with omni::core::createType(). This is the primary way Omniverse applications are able to instantiate concrete implementations of ABI-safe interfaces. See omni::core::createType() for a helpful wrapper around omni::core::ITypeFactory::createType().

In practice, there will be a single ITypeFactory active in the process space (accessible via omniGetTypeFactoryWithoutAcquire()). However, omni::core::ITypeFactory is not inherently a singleton, and as such multiple instantiations of the interface may exists. This can be used to create private type trees.

Unless otherwise noted, all methods in this interface are thread safe.

Subclassed by omni::core::Generated< omni::core::ITypeFactory_abi >

Public Functions

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.