carb/Framework.h
File members: carb/Framework.h
// Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#pragma once
#include "Defines.h"
#include "Memory.h"
#include "Types.h"
#include <cstddef>
#include <cstdint>
// free() can be #define'd which can interfere below, so handle that here
#ifdef free
# define CARB_FREE_UNDEFINED
# pragma push_macro("free")
# undef free
#endif
namespace carb
{
#define CARBONITE_MAJOR 0
#define CARBONITE_MINOR 6
constexpr struct Version kFrameworkVersion = { CARBONITE_MAJOR, CARBONITE_MINOR };
constexpr FourCC kCarb_FourCC = CARB_MAKE_FOURCC('C', 'A', 'R', 'B');
struct PluginRegistrationDesc
{
OnPluginRegisterFn onPluginRegisterFn;
OnPluginStartupFn onPluginStartupFn;
OnPluginShutdownFn onPluginShutdownFn;
GetPluginDepsFn getPluginDepsFn;
OnReloadDependencyFn onReloadDependencyFn;
OnPluginPreStartupFn onPluginPreStartupFn;
OnPluginPostShutdownFn onPluginPostShutdownFn;
OnPluginRegisterExFn onPluginRegisterExFn;
OnPluginStartupExFn onPluginStartupExFn = nullptr;
OnPluginRegisterEx2Fn onPluginRegisterEx2Fn = nullptr;
FourCC const checkValue{ kCarb_FourCC };
size_t const sizeofThis{ sizeof(PluginRegistrationDesc) };
OnPluginQuickShutdownFn onPluginQuickShutdownFn = nullptr;
Version frameworkVersion{ kFrameworkVersion };
};
struct PluginLoadingDesc
{
const char* const* searchPaths;
size_t searchPathCount;
bool searchRecursive;
const char* const* loadedFileWildcards;
size_t loadedFileWildcardCount;
const char* const* reloadableFileWildcards;
size_t reloadableFileWildcardCount;
bool unloadPlugins;
const char* const* excludedFileWildcards;
size_t excludedFileWildcardCount;
static PluginLoadingDesc getDefault()
{
static constexpr const char* defaultSearchPath = "";
static constexpr const char* defaultLoadedFileWildcard = "*.plugin";
return { &defaultSearchPath, 1, false, &defaultLoadedFileWildcard, 1, nullptr, 0, false, nullptr, 0 };
}
};
enum AcquireInterfaceFlags : uint64_t
{
eAIFDefaultType = 0,
eAIFFromInterfaceType,
eAIFFromLibraryType,
eAIFNumTypes,
fAIFTypeMask = 0xf,
fAIFOptional = (1 << 4),
fAIFNoInitialize = (1 << 5),
};
static_assert(eAIFNumTypes <= fAIFTypeMask, "Too many types for mask");
struct AcquireInterfaceOptions
{
size_t sizeofThis;
const char* clientName;
InterfaceDesc desc;
AcquireInterfaceFlags flags;
const void* typeParam;
};
CARB_ASSERT_INTEROP_SAFE(AcquireInterfaceOptions);
enum class LoadPluginResult : int32_t
{
eForbiddenPath = -3,
eInvalidArg = -2,
eFailed = -1,
eSucceeded = 0,
eSucceededAsOmniverseNativeInterface = 1,
eAlreadyLoaded = 2,
};
using ReleaseHookFn = void (*)(void* iface, void* userData);
using LoadHookFn = void (*)(const PluginDesc& plugin, void* userData);
CARB_DYNAMICLINK carb::Framework* acquireFramework(const char* appName, Version frameworkVersion = kFrameworkVersion);
CARB_DYNAMICLINK bool isFrameworkValid();
CARB_DYNAMICLINK const char* carbGetSdkVersion();
#define CARB_IS_SAME_SDK_VERSION(version) (strcmp(version, carbGetSdkVersion()) == 0)
CARB_DYNAMICLINK void releaseFramework();
CARB_DYNAMICLINK void quickReleaseFrameworkAndTerminate [[noreturn]] (int exitCode);
#if CARB_PLATFORM_WINDOWS
CARB_DYNAMICLINK void carbSignalHandler(int signal);
#endif
struct Framework
{
void loadPlugins(const PluginLoadingDesc& desc = PluginLoadingDesc::getDefault());
void(CARB_ABI* loadPluginsEx)(const PluginLoadingDesc& desc);
void(CARB_ABI* unloadAllPlugins)();
template <typename T>
T* acquireInterface(const char* pluginName = nullptr);
template <typename T>
T* tryAcquireInterface(const char* pluginName = nullptr);
template <typename T>
T* acquireInterface(const void* pluginInterface);
template <typename T>
T* tryAcquireInterface(const void* pluginInterface);
template <typename T>
T* acquireInterfaceFromLibrary(const char* libraryPath);
template <typename T>
T* tryAcquireInterfaceFromLibrary(const char* libraryPath);
template <typename T>
T* tryAcquireExistingInterface(const char* pluginName = nullptr);
template <typename T>
uint32_t getInterfacesCount();
template <typename T>
void acquireInterfaces(T** interfaces, uint32_t interfacesSize);
void*(CARB_ABI* acquireInterfaceWithClient)(const char* clientName, InterfaceDesc desc, const char* pluginName);
static_assert(kFrameworkVersion.major == 0, "Remove above function in next Framework version");
void*(CARB_ABI* tryAcquireInterfaceWithClient)(const char* clientName, InterfaceDesc desc, const char* pluginName);
static_assert(kFrameworkVersion.major == 0, "Remove above function in next Framework version");
void*(CARB_ABI* acquireInterfaceFromInterfaceWithClient)(const char* clientName,
InterfaceDesc desc,
const void* pluginInterface);
static_assert(kFrameworkVersion.major == 0, "Remove above function in next Framework version");
void*(CARB_ABI* tryAcquireInterfaceFromInterfaceWithClient)(const char* clientName,
InterfaceDesc desc,
const void* pluginInterface);
static_assert(kFrameworkVersion.major == 0, "Remove above function in next Framework version");
void*(CARB_ABI* acquireInterfaceFromLibraryWithClient)(const char* clientName,
InterfaceDesc desc,
const char* libraryPath);
static_assert(kFrameworkVersion.major == 0, "Remove above function in next Framework version");
void*(CARB_ABI* tryAcquireInterfaceFromLibraryWithClient)(const char* clientName,
InterfaceDesc desc,
const char* libraryPath);
static_assert(kFrameworkVersion.major == 0, "Remove above function in next Framework version");
uint32_t(CARB_ABI* getInterfacesCountEx)(InterfaceDesc interfaceDesc);
void(CARB_ABI* acquireInterfacesWithClient)(const char* clientName,
InterfaceDesc interfaceDesc,
void** interfaces,
uint32_t interfacesSize);
template <typename T>
void releaseInterface(T* pluginInterface);
void(CARB_ABI* releaseInterfaceWithClient)(const char* clientName, void* pluginInterface);
const PluginDesc&(CARB_ABI* getPluginDesc)(const char* pluginName);
const PluginDesc&(CARB_ABI* getInterfacePluginDesc)(void* pluginInterface);
void(CARB_ABI* getCompatiblePlugins)(InterfaceDesc interfaceDesc, PluginDesc* outPlugins);
size_t(CARB_ABI* getPluginCount)();
void(CARB_ABI* getPlugins)(PluginDesc* outPlugins);
void(CARB_ABI* tryReloadPlugins)();
bool(CARB_ABI* registerPlugin)(const char* clientName, const PluginRegistrationDesc& desc);
bool(CARB_ABI* unregisterPlugin)(const char* pluginName);
const PluginRegistrationDesc&(CARB_ABI* getBuiltinLoggingDesc)();
const PluginRegistrationDesc&(CARB_ABI* getBuiltinFileSystemDesc)();
template <class T>
void setDefaultPlugin(const char* pluginName);
void(CARB_ABI* setDefaultPluginEx)(const char* clientName, InterfaceDesc desc, const char* pluginName);
void(CARB_ABI* setReloadableTempPath)(const char* tempPath);
const char*(CARB_ABI* getReloadableTempPath)();
const char*(CARB_ABI* getBuildInfo)();
template <typename T>
T* verifyInterface(T* interfaceCandidate);
void*(CARB_ABI* verifyInterfaceEx)(InterfaceDesc desc, void* interfaceCandidate);
const PluginRegistrationDesc&(CARB_ABI* getBuiltinAssertDesc)();
const PluginRegistrationDesc&(CARB_ABI* getBuiltinThreadUtilDesc)();
LoadPluginResult(CARB_ABI* loadPlugin)(const char* libraryPath, bool reloadable, bool unload);
bool(CARB_ABI* unloadPlugin)(const char* libraryPath);
bool(CARB_ABI* addReleaseHook)(void* iface, ReleaseHookFn fn, void* user);
bool(CARB_ABI* removeReleaseHook)(void* iface, ReleaseHookFn fn, void* user);
CARB_DEPRECATED("Use carbReallocate() instead")
void*(CARB_ABI* internalRealloc)(void* prev, size_t newSize, size_t align);
static_assert(kFrameworkVersion.major == 0, "Remove Framework::internalRealloc in next Framework version");
CARB_DEPRECATED("Use carb::allocate() instead") void* allocate(size_t size, size_t align = 0)
{
return carb::allocate(size, align);
}
static_assert(kFrameworkVersion.major == 0, "Remove Framework::allocate in next Framework version");
CARB_DEPRECATED("Use carb::deallocate() instead") void free(void* p)
{
return carb::deallocate(p);
}
static_assert(kFrameworkVersion.major == 0,
"Remove Framework::free and CARB_FREE_UNDEFINED in next Framework version");
CARB_DEPRECATED("Use carb::reallocate() instead") void* reallocate(void* p, size_t size, size_t align = 0)
{
return carb::reallocate(p, size, align);
}
static_assert(kFrameworkVersion.major == 0, "Remove Framework::reallocate in next Framework version");
const char*(CARB_ABI* getSdkVersion)();
template <class T>
LoadHookHandle addLoadHook(const char* pluginName, LoadHookFn func, void* userData);
LoadHookHandle(CARB_ABI* internalAddLoadHook)(
const InterfaceDesc& iface, const char* plugin, const char* clientName, LoadHookFn fn, void* user, bool add);
bool(CARB_ABI* removeLoadHook)(LoadHookHandle handle);
void(CARB_ABI* registerScriptBinding)(BindingType type, const char* clientName, const char* scriptType);
void*(CARB_ABI* internalAcquireInterface)(const AcquireInterfaceOptions& options);
};
} // namespace carb
CARB_WEAKLINK CARB_HIDDEN const char* g_carbClientName;
CARB_WEAKLINK CARB_HIDDEN carb::Framework* g_carbFramework;
extern bool g_needToCall_CARB_GLOBALS_atGlobalScope;
#define CARB_FRAMEWORK_GLOBALS(clientName) \
CARB_HIDDEN bool g_needToCall_CARB_GLOBALS_atGlobalScope = carb::detail::setClientName(clientName);
namespace carb
{
namespace detail
{
inline bool setClientName(const char* clientName)
{
g_carbClientName = clientName;
return true;
}
} // namespace detail
inline Framework* getFramework()
{
return g_carbFramework;
}
inline void Framework::loadPlugins(const PluginLoadingDesc& desc)
{
return this->loadPluginsEx(desc);
}
template <typename T>
T* Framework::verifyInterface(T* interfaceCandidate)
{
const auto desc = T::getInterfaceDesc();
return static_cast<T*>(getFramework()->verifyInterfaceEx(desc, interfaceCandidate));
}
template <typename T>
T* Framework::acquireInterface(const char* pluginName)
{
const char* clientName = g_needToCall_CARB_GLOBALS_atGlobalScope ? g_carbClientName : nullptr;
if (this->internalAcquireInterface)
return static_cast<T*>(this->internalAcquireInterface(
{ sizeof(AcquireInterfaceOptions), clientName, T::getInterfaceDesc(), eAIFDefaultType, pluginName }));
else
return static_cast<T*>(this->acquireInterfaceWithClient(clientName, T::getInterfaceDesc(), pluginName));
}
template <typename T>
T* Framework::tryAcquireInterface(const char* pluginName)
{
const char* clientName = g_needToCall_CARB_GLOBALS_atGlobalScope ? g_carbClientName : nullptr;
if (this->internalAcquireInterface)
return static_cast<T*>(
this->internalAcquireInterface({ sizeof(AcquireInterfaceOptions), clientName, T::getInterfaceDesc(),
AcquireInterfaceFlags(eAIFDefaultType | fAIFOptional), pluginName }));
else
return static_cast<T*>(this->tryAcquireInterfaceWithClient(clientName, T::getInterfaceDesc(), pluginName));
}
template <typename T>
T* Framework::acquireInterface(const void* pluginInterface)
{
const char* clientName = g_needToCall_CARB_GLOBALS_atGlobalScope ? g_carbClientName : nullptr;
if (this->internalAcquireInterface)
return static_cast<T*>(
this->internalAcquireInterface({ sizeof(AcquireInterfaceOptions), clientName, T::getInterfaceDesc(),
eAIFFromInterfaceType, pluginInterface }));
else
return static_cast<T*>(
this->acquireInterfaceFromInterfaceWithClient(clientName, T::getInterfaceDesc(), pluginInterface));
}
template <typename T>
T* Framework::tryAcquireInterface(const void* pluginInterface)
{
const char* clientName = g_needToCall_CARB_GLOBALS_atGlobalScope ? g_carbClientName : nullptr;
if (this->internalAcquireInterface)
return static_cast<T*>(this->internalAcquireInterface(
{ sizeof(AcquireInterfaceOptions), clientName, T::getInterfaceDesc(),
AcquireInterfaceFlags(eAIFFromInterfaceType | fAIFOptional), pluginInterface }));
else
return static_cast<T*>(
this->tryAcquireInterfaceFromInterfaceWithClient(clientName, T::getInterfaceDesc(), pluginInterface));
}
template <typename T>
T* Framework::acquireInterfaceFromLibrary(const char* libraryPath)
{
const char* clientName = g_needToCall_CARB_GLOBALS_atGlobalScope ? g_carbClientName : nullptr;
if (this->internalAcquireInterface)
return static_cast<T*>(this->internalAcquireInterface(
{ sizeof(AcquireInterfaceOptions), clientName, T::getInterfaceDesc(), eAIFFromLibraryType, libraryPath }));
else
return static_cast<T*>(
this->acquireInterfaceFromLibraryWithClient(clientName, T::getInterfaceDesc(), libraryPath));
}
template <typename T>
T* Framework::tryAcquireInterfaceFromLibrary(const char* libraryPath)
{
const char* clientName = g_needToCall_CARB_GLOBALS_atGlobalScope ? g_carbClientName : nullptr;
if (this->internalAcquireInterface)
return static_cast<T*>(
this->internalAcquireInterface({ sizeof(AcquireInterfaceOptions), clientName, T::getInterfaceDesc(),
AcquireInterfaceFlags(eAIFFromLibraryType | fAIFOptional), libraryPath }));
else
return static_cast<T*>(
this->tryAcquireInterfaceFromLibraryWithClient(clientName, T::getInterfaceDesc(), libraryPath));
}
template <typename T>
T* Framework::tryAcquireExistingInterface(const char* pluginName)
{
const char* clientName = g_needToCall_CARB_GLOBALS_atGlobalScope ? g_carbClientName : nullptr;
return this->internalAcquireInterface ?
static_cast<T*>(this->internalAcquireInterface(
{ sizeof(AcquireInterfaceOptions), clientName, T::getInterfaceDesc(),
AcquireInterfaceFlags(eAIFDefaultType | fAIFOptional | fAIFNoInitialize), pluginName })) :
nullptr;
}
template <typename T>
uint32_t Framework::getInterfacesCount()
{
const InterfaceDesc desc = T::getInterfaceDesc();
return this->getInterfacesCountEx(desc);
}
template <typename T>
void Framework::acquireInterfaces(T** interfaces, uint32_t interfacesSize)
{
const InterfaceDesc desc = T::getInterfaceDesc();
const char* clientName = g_needToCall_CARB_GLOBALS_atGlobalScope ? g_carbClientName : nullptr;
this->acquireInterfacesWithClient(clientName, desc, reinterpret_cast<void**>(interfaces), interfacesSize);
}
template <typename T>
void Framework::releaseInterface(T* pluginInterface)
{
(void)(T::getInterfaceDesc()); // Compile-time check that the type is plugin interface
const char* clientName = g_needToCall_CARB_GLOBALS_atGlobalScope ? g_carbClientName : nullptr;
this->releaseInterfaceWithClient(clientName, pluginInterface);
}
template <typename T>
void Framework::setDefaultPlugin(const char* pluginName)
{
const char* clientName = g_needToCall_CARB_GLOBALS_atGlobalScope ? g_carbClientName : nullptr;
this->setDefaultPluginEx(clientName, T::getInterfaceDesc(), pluginName);
}
template <typename T>
LoadHookHandle Framework::addLoadHook(const char* pluginName, LoadHookFn func, void* user)
{
const char* clientName = g_needToCall_CARB_GLOBALS_atGlobalScope ? g_carbClientName : nullptr;
return this->internalAddLoadHook(T::getInterfaceDesc(), pluginName, clientName, func, user, true);
}
} // namespace carb
#ifdef CARB_FREE_UNDEFINED
# pragma pop_macro("free")
# undef CARB_FREE_UNDEFINED
#endif