Hi AgentMilkshake1,
Adding the DLL to PublicDelayLoadDlls is only part of the solution - the engine needs to know where the DLL lives, so it can find it once it is required. This can be achieved in a few ways.
The first, and easiest (but least scalable) is to simply copy the DLL to the binary folder of your game/the engine. Binaries will automatically look in their launch directory for DLLs, so generally this should solve the problem.
The next solution is to manually add the DLL folder location to the DLLSearchPath in FPlatformProcess prior to requiring the DLL. This informs the engine where the DLL will be located, so it can be loaded dynamically when needed.
Unfortunately, this approach appears to have been broken in 4.11 (the engine will fail to find the DLL, despite having the full path made available).
To remedy this 4.11 issue, you can manually load the DLL directly, so it will be available when it is required. This isn’t ideal, because it means the overhead of loading the library exists, regardless of whether you actually try to use
it.
Anyway, here’s the code solution. This is written on the assumption that you are loading the DLL inside a plugin (engine or project plugin, should work with both). It should be fairly easy to rework this for plugins included in the
project.
void FPluginModule::StartupModule()
{
//Search project plugins folder for Dll
FString dllName = "DllName.dll";
if (SearchForDllPath(FPaths::GamePluginsDir(), dllName))
{
}
else if (SearchForDllPath(FPaths::EnginePluginsDir(), dllName)) //Failed in project dir, try engine plugins dir
{
}
else
{
//Stop loading - plugin required DLL to load successfully
checkf(false, TEXT("Failed to load dll"));
}
}
bool FPluginModule::SearchForDllPath(FString _searchBase, FString _dllName)
{
//Search Plugins folder for an instance of Dll.dll, and add to platform search path
TArray<FString> directoriesToSkip;
IPlatformFile &PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
FLocalTimestampDirectoryVisitor Visitor(PlatformFile, directoriesToSkip, directoriesToSkip, false);
PlatformFile.IterateDirectory(*_searchBase, Visitor);
for (TMap<FString, FDateTime>::TIterator TimestampIt(Visitor.FileTimes); TimestampIt; ++TimestampIt)
{
const FString file = TimestampIt.Key();
const FString filePath = FPaths::GetPath(file);
const FString fileName = FPaths::GetCleanFilename(file);
if (fileName.Compare(_dllName) == 0)
{
FPlatformProcess::AddDllDirectory(*filePath); // only load dll when needed for use. Broken with 4.11.
FPlatformProcess::GetDllHandle(*file); // auto-load dll with plugin - needed as 4.11 breaks above line.
return true;
}
}
return false;
}
A final note, if this DLL is part of the game, rather than just editor, and you want it to be packaged in with your game for release, the following line in your build.cs should automatically stage the DLL for distribution (replace
PathToDLL with DLL path, relative to build.cs file location):
RuntimeDependencies.Add(new RuntimeDependency(PathToDLL));
Hope this helps!