Creating GDAL Plugin for Unreal - jgoffeney/Cesium4Unreal GitHub Wiki

Back

This is a description of the steps for creating an Unreal GDAL Plugin for Windows. I use PluginExample as the project name and LibGDAL as the plugin name.

Creating a GDAL Plugin

Windows's GDAL Libraries

The site GIS Internals has releases of binaries and libraries. For your version of Visual Studio and architecture download the zip's containing the binaries and libraries.

GISInternals

The file ending with libs.zip contains static GDAL .lib files and headers and the other file contains GDAL .dll files.

Unreal

Project

Create a new project using the Games Project Categories with a Blank template and project settings of C++ and No Starter Content.

BaseProject

The file PluginExample.Build.cs is used by the Unreal Build Tool to generate the project and we will add the plugin reference to it.

Plugins

  • Add a new blank plugin
    • Edit->Plugins and press New Plugin
    • Create a blank plugin by selecting the Blank template

PluginProject

Add GDAL Files
  • Add GDAL Library Files to the Plugin
    • Add a ThirdParty directory to the Plugins/LibGDAL/Source.
    • Unzip the downloaded file ending with lib.zip
    • Copy the include and lib directories into the ThirdParty directory.

GdalLib

  • Add GDAL Binary files to the Plugin
    • Unzip the other downloaded file of binaries
    • Copy the contents of the bin folder and paste into the Plugins/LibGDAL/Binaries/Win64 directory.

GdalBin

Note: at this point Visual Studio will not reflect the added files.

Update LibGDAL.Build.cs

Update the plugin's build rules file to find the GDAL include and static library files.

// Copyright Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;
using System.IO;

public class LibGDAL : ModuleRules
{
	public LibGDAL(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;

		// Add the GDAL header files		
		PublicIncludePaths.AddRange(
			new string[] {
				Path.Combine(ModuleDirectory, "../ThirdParty/include")
			}
			);

		// Add the GDAL static libraries
		string staticLibPath = Path.Combine(ModuleDirectory, "../ThirdParty/lib");
		string[] libraryFiles = Directory.GetFiles(staticLibPath, "*.lib", SearchOption.TopDirectoryOnly);
		PublicAdditionalLibraries.AddRange(libraryFiles);

		PrivateIncludePaths.AddRange(
			new string[] {
				// ... add other private include paths required here ...
			}
			);
			
		
		PublicDependencyModuleNames.AddRange(
			new string[]
			{
				"Core",
				// ... add other public dependencies that you statically link with here ...
			}
			);
			
		
		PrivateDependencyModuleNames.AddRange(
			new string[]
			{
				"CoreUObject",
				"Engine",
				"Slate",
				"SlateCore",
				// ... add private dependencies that you statically link with here ...	
			}
			);
		
		
		DynamicallyLoadedModuleNames.AddRange(
			new string[]
			{
				// ... add any modules that your module loads dynamically here ...
			}
			);
	}
}
Update PluginExample.Build.cs

Update the Unreal project build file to add the LibGDAL plugin.

// Copyright Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class PluginExample : ModuleRules
{
	public PluginExample(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "LibGDAL" });

		PrivateDependencyModuleNames.AddRange(new string[] {  });

		// Uncomment if you are using Slate UI
		// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
		
		// Uncomment if you are using online features
		// PrivateDependencyModuleNames.Add("OnlineSubsystem");

		// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
	}
}

Testing

Within the Unreal Editor create a C++ object based on Pawn to test. Below is my example as GdalPawn where I added:

  • Includes
    • #include <ThirdParty/include/gdal.h>
  • BeginPlay()
    • The GDAL code to register GDAL, get the number of GDAL drivers and write to the editor Output Log.
// Fill out your copyright notice in the Description page of Project Settings.

#include "GdalPawn.h"
#include <ThirdParty/include/gdal.h>

// Sets default values
AGdalPawn::AGdalPawn()
{
 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
}

// Called when the game starts or when spawned
void AGdalPawn::BeginPlay()
{
	GDALAllRegister();
	int driverCount = GDALGetDriverCount();
	UE_LOG(LogTemp, Warning, TEXT("Driver Count %d"), driverCount);

	Super::BeginPlay();	
}

// Called every frame
void AGdalPawn::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

// Called to bind functionality to input
void AGdalPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
}

Drag the pawn into the editor view and press play. Near the bottom of the log the message will be displayed and the plugin is working.

OutputLog

Usage Notes

GDALAllRegister()

The way Unreal Engine loads modules into processes means calling GDALAllRegister() within a convenient initialization function may not work with your code. Either call it before using GDAL or create a wrapper class that ensures it has been called prior to using GDAL.

Troubleshooting

Loading Error

LoadError

When loading the Unreal project sometimes the error occurs with the text:

There may be an operating system error, the module may not be properly set up, or a plugin which has been included into the build has not been turned on.

To find the actual problem go to your project directory and go into Saved/Logs and open the most recent log file. My error indicates a DLL is missing and then follows with each directory where the loader is looking for it.

LogWindows: Failed to load 'C:/Users/Jason Goffeney/OneDrive/Documents/Unreal Projects/GdalPluginTest/GdalBlank2/Binaries/Win64/UE4Editor-GdalBlank2.dll' (GetLastError=126)
LogWindows:   Missing import: gdal303.dll

Can't Find Headers

If you try to add a header file to one of your Unreal files such as a Pawn or Actor derived class but on compile it is not found then make sure you added your plugin to the project build file. For my project GdalBlank2 I opened the file GdalBlank2.Build.cs and to the PublicDependenciesModuleNames array I added the name of my plugin LibGDAL. Now the project and Visual Studio's Intellisense can locate the library headers I added to my plugin.

using UnrealBuildTool;

public class GdalBlank2 : ModuleRules
{
	public GdalBlank2(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "LibGDAL" });

		PrivateDependencyModuleNames.AddRange(new string[] {  });

		// Uncomment if you are using Slate UI
		// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
		
		// Uncomment if you are using online features
		// PrivateDependencyModuleNames.Add("OnlineSubsystem");

		// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
	}
}

Linking Errors On Using GDAL Functions

If the code for the GDAL has linking errors referring to GDALAllRegister() or GDALGetDriverCount() then check the library path staticLibPath within LibGDAL.Build.cs actually is the directory containing the .lib files.

cpl_port.h

Under Unreal 5 the GDAL file cpl_port.h causes warnings which Unreal treats as errors such as shown below. This should not be an error since it is a portability file specifically looking for other compilers like GNU C and Clang.

'__GNUC__' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'

A workaround is to disable the warning within the file.

#pragma warning(disable: 4668)

Third Party

Naming

I find it useful to make sure the plugin name is distinct from the library name. If you name your plugin GDAL then the project will have a GDAL.h file for the plugin while the actual GDAL source will have a "gdal.h" file. It can get confusing which is why the plugin above is named LibGDAL.