1
\$\begingroup\$

I am trying to create a runnable object to run code in a background thread. It's used to generate a level and it compiles as long as I don't include it somewhere. I've tried including it in a couple different classes and it fails.

.h

#pragma once

#include "CoreMinimal.h"

class ULevelGeneratorParams;
class ULevelData;

/**
 * Performs the actions of generating a level in a background thread.
 */
class MINESEEKER_API GenerateLevelRunnable : public FRunnable // as soon as I include this class in another class, FRunnable becomes an unknown type
{
public:

    static GenerateLevelRunnable Start(ULevelGeneratorParams *parameters);

    GenerateLevelRunnable();
    ~GenerateLevelRunnable();

    virtual bool Init();
    virtual uint32 Run();
    virtual void Stop();

private:

    static const int32 MINES_EASY = 10;
    static const int32 MINES_MEDIUM = 50;
    static const int32 MINES_HARD = 100;

    static const int32 WIDTH_HEIGHT_EASY = 10;
    static const int32 WIDTH_HEIGHT_MEDIUM = 20;
    static const int32 WIDTH_HEIGHT_HARD = 30;

    static ULevelGeneratorParams *Parameters;

    // Generates a unique vector and places it into the provided array.
    void GenerateUniqueVector(TArray<FVector2D> *locations, ULevelData *data);
};

c++

#include "GenerateLevelRunnable.h"
#include "Runnable.h"
#include "LevelGeneratorParams.h"
#include "LevelData.h"

GenerateLevelRunnable GenerateLevelRunnable::Start(ULevelGeneratorParams *parameters)
{
    GenerateLevelRunnable::Parameters = parameters;
    return new GenerateLevelRunnable();
}

GenerateLevelRunnable::GenerateLevelRunnable()
{
}

GenerateLevelRunnable::~GenerateLevelRunnable()
{
    delete GenerateLevelRunnable::Parameters;
    GenerateLevelRunnable::Parameters = NULL;
}

bool GenerateLevelRunnable::Init()
{
   return true;
}

uint32 GenerateLevelRunnable::Run()
{
    ULevelData *data = NewObject<ULevelData>();
    TArray<FVector2D> mineLocations;

    EDifficulty difficulty = GenerateLevelRunnable::Parameters->GetDifficulty();
    switch (difficulty)
    {
    case EDifficulty::EASY:
        data->SetWidth(WIDTH_HEIGHT_EASY);
        data->SetHeight(WIDTH_HEIGHT_EASY);

        for (int8 i = 0; i < MINES_EASY; i++)
        {
            GenerateUniqueVector(&mineLocations, data);
        }

        break;

    case EDifficulty::MEDIUM:
        data->SetWidth(WIDTH_HEIGHT_MEDIUM);
        data->SetHeight(WIDTH_HEIGHT_MEDIUM);

        for (int8 i = 0; i < MINES_MEDIUM; i++)
        {
            GenerateUniqueVector(&mineLocations, data);
        }

        break;

    case EDifficulty::HARD:
        data->SetWidth(WIDTH_HEIGHT_HARD);
        data->SetHeight(WIDTH_HEIGHT_HARD);

        for (int8 i = 0; i < MINES_HARD; i++)
        {
            GenerateUniqueVector(&mineLocations, data);
        }

        break;

    default:
        checkf(false, TEXT("Value for difficulty is not valid"));
        break;
}

data->SetMineLocations(mineLocations);
    return uint32();
}

void GenerateLevelRunnable::Stop()
{
}

void GenerateLevelRunnable::GenerateUniqueVector(TArray<FVector2D>* locations, ULevelData * data)
{
    FVector2D location;
    location.X = FMath::RandRange(1, data->GetWidth());
    location.Y = FMath::RandRange(1, data->GetWidth());

    if (locations->Contains(location))
    {
        GenerateUniqueVector(locations, data);
    }
    else
    {
        locations->Add(location);
    }
}

Here is the error I am getting

CompilerResultsLog: Error: GeneratBlueprintFunctionLibrary.cpp.obj : error LNK2019: unresolved external symbol "public: virtual __cdecl GenerateLevelRunnable::~GenerateLevelRunnable(void)" (??1GenerateLevelRunnable@@UEAA@XZ) referenced in function "public: virtual void * __cdecl GenerateLevelRunnable::`vector deleting destructor'(unsigned int)" (??_EGenerate
LevelRunnable@@UEAAPEAXI@Z)
CompilerResultsLog: Error: GeneratBlueprintFunctionLibrary.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl GenerateLevelRunnable::Init(void)" (?Init@GenerateLevelRunnable@@UEAA_NXZ)
CompilerResultsLog: Error: GeneratBlueprintFunctionLibrary.cpp.obj : error LNK2001: unresolved external symbol "public: virtual unsigned int __cdecl GenerateLevelRunnable::Run(void)" (?Run@GenerateLevelRunnable@@UEAAIXZ)
CompilerResultsLog: Error: GeneratBlueprintFunctionLibrary.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl GenerateLevelRunnable::Stop(void)" (?Stop@GenerateLevelRunnable@@UEAAXXZ)
CompilerResultsLog: Error: C:\dev\projects\ue4\MineSeeker\Binaries\Win64\UE4Editor-MineSeeker-2451.dll : fatal error LNK1120: 4 unresolved externals
CompilerResultsLog: ERROR: UBT ERROR: Failed to produce item: C:\dev\projects\ue4\MineSeeker\Binaries\Win64\UE4Editor-MineSeeker-2451.dll
\$\endgroup\$
2
\$\begingroup\$

LNK2019 is a linker error, not a compiler error. The error (the first one, at least) is telling you that the linker cannot find the definition of the symbol GenerateLevelRunnable::~GenerateLevelRunnable (and various other functions) that you declared in your header. They are in your source file, however, so it's not as simple as you just having forgotten to implement them.

The error states that the reference is within an object file called GeneratBlueprintFunctionLibrary.cpp.obj, that is, the object file for the GeneratBlueprintFunctionLibrary.cpp file. This suggests then that whatever is linking the UE4Editor-MineSeeker-2451.dll output file is not including your GenerateLevelRunnable class's compiled object file in the linker input command.

Since this is UE, the Unreal build system is responsible for feeding the appropriate files to the appropriate build tools. One typical reason for a file not being supplied to the linker is that you failed to configure your (Unreal) module's dependencies correctly. You may need to add the module containing your GenerateLevelRunnable class to the public or private dependency list of the module being compiled.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks the clean build suggestion show an error that for some reason was not being shown in UE4's compiler results. I fixed that error and now this is all working good. \$\endgroup\$ – Jason Crosby Dec 4 '17 at 23:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.