carb::extras::loadLibrary

Defined in carb/extras/Library.h

inline LibraryHandle carb::extras::loadLibrary(const char *libraryName, LibraryFlags flags = 0)

Attempts to load a named library into the calling process.

This attempts to dynamically load a named library into the calling process. If the library is already loaded, the reference count of the library is increased and a handle to it is returned. If the library was not already loaded, it is dynamically loaded and a handle to it is returned; its reference count will be one. Each call to this function should be balanced by a call to unloadLibrary() when the library is no longer needed.

Libraries that were loaded as part of the process’s dependencies list will be ‘pinned’ and their reference count will not be changed by attempting to load them. It is still safe to unloadLibrary() on handles for those libraries.

Windows

This function calls LoadLibraryEx with LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR and LOAD_LIBRARY_SEARCH_DEFAULT_DIRS to load libraries. If this fails, the default search path is instead used. If ERROR_FILENAME_EXCED_RANGE is returned, the LoadLibraryEx call is repeated with the filepath preceded with a prefix to disable string parsing. If the module or a dependent module is not found, GetLastError() typically reports ERROR_MOD_NOT_FOUND. In order to determine which DLL library is missing there are a few options:

  • Enable Show Loader Snaps with the gflags tool, which is available with Debugging Tools for Windows. Running the process in a debugger or with access to debug output will then show log messages from the Windows loader.

  • The same debug output can be enabled by setting the 32-bit value at ntdll.dll!LdrpDebugFlags to 0x1. This value must be accessed in a debugger with symbols for ntdll.dll.

  • Alternately using a modern Dependencies tool will reveal missing dependencies for a library without a debugger, although it may not show the actual error that led to loadLibrary failing.

Linux

This function calls dlopen with the RTLD_LAZY flag (or RTLD_NOW if fLibFlagNow is specified). If fLibFlagDeepBind is specified, RTLD_DEEPBIND is also used. It is possible for the underlying dlopen() call to succeed without a dependent library able to load. In this case, the dynamic loader destroys the link map, so symbol lookup on the module will fail. This condition is detected and treated as an error condition. To have dynamic loader debug output displayed, use the LD_DEBUG environment variable set to a value such as files, libs or all. Typically the output is printed to stdout, but the LD_DEBUG_OUTPUT can be set to the name of a file to instead log to the file. The ldd command-line tool can be used to print the dependent libraries required by an executable or library.

MacOS

This function calls dlopen with the RTLD_LAZY flag (or RTLD_NOW if fLibFlagNow is specified). To have the dynamic loader debug output displayed, use the DYLD_PRINT_LIBRARIES environment variable. The otool command-line tool with the -L option will print out the dependent libraries required by an executable or library.

MacOS

If the requested library name is nullptr, the expectation from the caller is that the handle to the process’ main executable image will be returned. Unfortunately on MacOS, the RTLD_DEFAULT symbol is returned instead as a pseudo-handle to the main executable module. This is valid to pass to other functions such as getLibrarySymbol() and getLibraryFilenameByHandle() however.

Note

A library may fail to load because of a dependent library, but the error message may seem like the requested library is causing the failure.

Parameters
  • libraryName[in] The name of the library to attempt to load. This may be either a relative or absolute path name. This should be a UTF-8 encoded path. If the fLibFlagMakeFullLibName flag is used, the library name may omit any platform specific prefix or file extension. The appropriate platform specific name will be generated internally using createLibraryNameForModule(). If nullptr is provided, the executable module is retrieved instead. On Windows this handle need not be closed with unloadLibrary() as it does not increment the reference count, but on MacOSX and Linux it increments the reference count and should therefore be passed to unloadLibrary().

  • flags[in] Flags to control the behavior of the operation. This defaults to 0.

Returns

A handle to the library if it was already loaded in the process. This handle should be cleaned up by unloadLibrary() when it is no longer necessary. nullptr is returned if the library could not be found, or loading fails for some reason (use getLastLoadLibraryError()).