Thank you both. I solved the problem in a different way, but it took me days. I struggled to figure this out without sleeping, I wish there were more resources for plugins.
Solution:
First of all, I created a DLL from scratch in a Visual Studio project to learn how Third Party DLLs work. And I learned to link this DLL I created in a new Visual Studio project.
Tutorial: Walkthrough: Create and use your own Dynamic Link Library (C++) | Microsoft Learn
As for Unreal Engine;
I added a Build.cs to the source file section of the DLL files. I defined it as external module. Then I added the name “YourExternalModule” to PrivateDependencyModuleNames.

I used PublicDelayLoadDLLs and RuntimeDependencies. These were necessary both to load the DLL into the engine and to copy the DLL to the correct path after it was created.
// Add any include paths for the plugin
PublicIncludePaths.Add(Path.Combine(ModuleDirectory));
// Add any import libraries or static libraries
PublicAdditionalLibraries.Add(Path.Combine(ModuleDirectory, "x64", "Release", "NVMLManagerLibrary.lib"));
// Delay-load the DLL, so we can load it from the right place first
PublicDelayLoadDLLs.Add("NVMLManagerLibrary.dll");
string sourcePath = "$(ProjectDir)/Plugins/DryreLUIEssentialsPlugin/Source/ThirdParty/NVML/NVMLManagerLibrary/x64/Release/NVMLManagerLibrary.dll";
string destinationPath = "$(ProjectDir)/Binaries/Win64/NVMLManagerLibrary.dll";
string buildPath = "$(BinaryOutputDir)/NVMLManagerLibrary.dll";
Important: When building the game, make sure that the DLL files are copied to the build folder! Otherwise, even though it seems to work in the DLL engine, it will not work in the game build and you will have to copy the DLL files manually. It’s not right to copy manually, so you definitely need to use “RuntimeDependencies”.
When loading DLLs with DelayLoadDLLs, both the engine and the game build path must be common/same. Make sure you pay attention to this.
Finally, I defined a LibraryHandle (void) in YourPluginName.h private to load the appropriate DLL file according to which RHI is used.
private:
/** Handle to the test dll we will load */
void* LibraryHandle;
};
StartupModule() is auto-loads the DLL for me. Here’s my code:
#include "Modules/ModuleManager.h"
#include "Misc/Paths.h"
FString myprojectDir = FPaths::ProjectDir();
// DEVELOPER NOTE: Make sure to LibraryHande DLLs are in the Binaries folder!
if(IsRHIDeviceNVIDIA())
{
// Add on the relative location of the third party dll and load it
FString LibraryPathNVML;
#if PLATFORM_WINDOWS
LibraryPathNVML = FPaths::Combine(*myprojectDir, TEXT("/Binaries/Win64/NVMLManagerLibrary.dll"));
#endif // PLATFORM_WINDOWS
LibraryHandle = !LibraryPathNVML.IsEmpty() ? FPlatformProcess::GetDllHandle(*LibraryPathNVML) : nullptr;
}
else if(IsRHIDeviceAMD())
{
FString LibraryPathADL;
#if PLATFORM_WINDOWS
LibraryPathADL = FPaths::Combine(*myprojectDir, TEXT("/Binaries/Win64/ADLManagerLibrary.dll"));
#endif // PLATFORM_WINDOWS
LibraryHandle = !LibraryPathADL.IsEmpty() ? FPlatformProcess::GetDllHandle(*LibraryPathADL) : nullptr;
}
if (LibraryHandle)
{
if(IsRHIDeviceNVIDIA())
{
nvGPUInitializeNVML();
}
else if(IsRHIDeviceAMD())
{
adlInitializeADL();
}
else if(IsRHIDeviceIntel())
{
// Initialize Intel
}
else if(IsRHIDeviceApple())
{
// Initialize Apple
}
else
{
// Initialize Other Brand
}
}
else
{
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("DryreLUIEssentialsError", "Failed to load Third Party library"));
}
Hope this helps!