Init a TArray

Hi! I have an array of custom UObjects called Squeezie.

I define in the .h an array:

TArray<USqueezie*> MySqueezies;

then i want to add one item in a function like this:

MySqueezies.Add(ThisNewSqueezie);

I get this error:

ld.lld: error: undefined symbol: AMyBLE_CPP::MySqueezies

so My array is null = not initialized.
How do I initialize an array with no items on it?

Thanks!

Hi there!

In your case it does not mean your array is null, 1st because it is not a pointer. The error message just says that the symbol is undefined at the moment the linker tries to find it. Such error usually happens when you try to access a class from an outside class function and the class is not exported. You need to use the module export define name in front of your class name, so anywhere in your code you might have done like below:

UCLASS()
class AMyBLE : public AActor
{

}

and you miss:

UCLASS()
class XXXXXXX_API AMyBLE : public AActor
{

}

that XXXXXXX_API you will find at the file where you have IMPLEMENT_MODULE(X, Y) or IMPLEMENT_PRIMARY_GAME_MODULE(X, Y, Z), which you should use the Y word there and add the _API suffix.

Hi Nilson!! thank you very much for your reply.
This is my situation:

I have an UOBject named Squeezy:

.h:

#pragma once

#include “CoreMinimal.h”
//#include “SqueezyData.h”
//#include “UObject/NoExportTypes.h”
#include “Squeezy.generated.h”

UCLASS(BlueprintType) class ANDROIDAPITEMPLATE_API USqueezy : public UObject
{
GENERATED_BODY()

public:
USqueezy();
FVector Acceleration;
FVector Displacement;
FQuat Element;
int Pressure;
int Step;
int State;
int Key;
long Time;
bool ButtonStatus;
FString MAC;
FString Name;

};

.cpp:

#include “Squeezy.h”

USqueezy::USqueezy() { }


Then I have an Actor that wants to use that object:

in the .h:

#include “Squeezy.h”
.
.
.
UFUNCTION()
static void ConvertToSqueezy(FString Obj);
.
.
.
in cpp:

void AMyBLE_CPP::ConvertToSqueezy(FString Obj)
{
USqueezy* ThisSqueezy;
ThisSqueezy = NewObject();
.
.
.
ThisSqueezy->Pressure = myPressure;
ThisSqueezy->MAC = myMac;
ThisSqueezy->Name = myname;

GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::White, FString::Printf(TEXT("Velocidad: %i"),ThisSqueezy->Pressure));

This works PERFECT…no errors.
So I can create an object inside my function of type USqueezie* , add parameters on it and print to debugscreen the data. No errors.

But I just created and used the object inside the same function.
My problem is when i defina a TARRAY of this object as:
static TArray<USqueezy*> MySqueezies;

in the .h

and try to add in the function the generated squeezie inside the array like this:

if (MySqueezies.Find(ThisSqueezy) != INDEX_NONE) MySqueezies.RemoveAt(MySqueezies.Find(ThisSqueezy));
MySqueezies.Add(ThisSqueezy);

it gives me this error:

LogPlayLevel: Error: ld.lld: error: undefined symbol: AMyBLE_CPP::MySqueezies

I see now. In your case, you made the Array a static member, and every static member for a class must be initialized or else it would be as there is no instance for it. To fix that, you need to include at the .cpp file for the class you placed that static Array the following lines to create the instance for that static member inside the class:

TArray<USqueezy *> AMyBLE_CPP::MySqueezies;

and that’s it. It is just a C++ rule, nothing specific for UE4.

You can read more here: Static Members of a C++ Class

You must always set TArrays to how many you need. Then if you want you can put in a nullptr in each to start them. Then once they go into actual use you can fill them with what you want.
//put this in the constructor
MySqueezies.SetNum(Howmany) ;//will initialize it to hold that many.

//will hold addresses to the actual info, put this in beginplay();
for( int32 i = 0; i <MySqueezies.Num(); i++ )
{
MySqueezies[i] = nullptr;//set them all to null ptr, ready for use now
}

Hi Nilson!

If i add the line in the .cpp BeginPlay() function liek this:

TArray<USqueezy *> AMyBLE_CPP::MySqueezies;

I get this error:

/MyBLE_CPP.cpp(25,32): error: definition or redeclaration of ‘MySqueezies’ not allowed inside a function
LogPlayLevel: TArray<USqueezy*> AMyBLE_CPP::MySqueezies;
LogPlayLevel: ~~~~~~~~~~~~^

Hi! I just want to initialize without members (because I want to add/remove members later) anyway I try just MySqueezies.SetNum(1) ; to see what happens and this is the error* (*I am adding this line in the beginplay() function):

Error: ld.lld: error: undefined symbol: AMyBLE_CPP::MySqueezies

I tried put 10 instead 1 same error.

I dont understan why I MUST set how many members i need in the array when working on blueprints you just add/remove/etc on runtime without problems. Define how many members will you use in the array before use it sounds strange :frowning:

when i define one as static . if i do not set how many it will be, i have compile errors. If you are trying to use the array with out setting it to something and not static, Then use add() remove() append(). add them that way.

I am defining as you suggest with an arbitraty number (like 10) and I get the error anyway :frowning:

I just noticed the main problem is not because of the Array. It is because I define the variable outside the function (as public static TArray<USqueezy*> MySqueezies; in the .h)
if i declare a regular variable like:

public static USqueezy* test;

and then inside the function i put:

test = thisSqueezy;

i have the same undefined symbol error

If you have not put anything into it or define its length. You are going to get an error when trying to use it. The array must contain something or it will error when trying to access it as there is nothing to access as you have not put anything into it.

So if you go and say set up an tarray like so
TArray<YourClass*> Testarray;

The in constructor do this or do not do this and use add() or insert or append()
Testarray.SetNum(10);

At that point you should have 10 Testarray to put stuff into. if you do not use SetNum().
Then use add(); or addunique(); or append() or insert(). and those should work.

Good luck with this.

I noticed problem is not with arrays.
I tried this and gave me same undefined symbol: AMyBLE_CPP::MySqueezies error:

in the .h:

static USqueezy* testSqueez;

in the function (.cpp):

testSqueez = ThisSqueezy;

*ThisSqueezy is totally valid object with right data filled inside.

basically my error is trying to put an object that was generated inside a function like this:

void AMyBLE_CPP::ConvertToSqueezy(FString Obj)
{
USqueezy* ThisSqueezy;
ThisSqueezy = NewObject();
.
.
.

inside a static object defined in the .h file.

What do i want to achieve?

I want an array of valid objects.

convertToSqueezy function creates a valid squeezy object with specific data. Then I have a global

Array of squeezies that i want to keep updated with valid and not repeated squeezies doing this:

if (MySqueezies.Find(ThisSqueezy) != INDEX_NONE) {MySqueezies.RemoveAt(MySqueezies.Find(ThisSqueezy));}
MySqueezies.Add(ThisSqueezy);

that is: if ThisSqueezy is in the array then delete it . Then add the new squeezie.

It is necessary to declare it outside of any function, just at the .cpp body. See the article. I was not aware of the need for the TArray to set the amount of instances it would have. It might be necessary to change the way you want that to work. I will give this a thought and will let you know.

use this then addunique(); that is the only thing that will keep every instance different if they are the same it wont add it. Example if your putting in numbers it wont let you put in the same number twice.

addunique(NewSqueeze);

hey!! that is a great tip! thanks!!

Anyway the base problem stills…and is not related to arrays. still figuring aout where the problem is.

I have a variable (A) of class XX declared in the. .h file (public static otherwise i get errors)

then inside a function in the .cpp i have a valid (B) of class XX and I just try to assign in the funciont: A = B; and i get this : A → undefined symbol

Still trying to figure it out…

You could use TMap instead of TArray. TMap uses a key to access the element and it won’t allow duplicates, so you won’t be able to insert a duplicate inside the container.

Static types must be initialized in the CPP file, outside any function body and outside any class body.

Also, there’s a dozen ways to initialize types in C++. After a decade of debate, the C++ Gods (creators of the language) came to the conclusion that you should initialize containers and types with a ’ {} '.

So, in the CPP file, NO function or class body, you do this:

TArray< USqueezy* > AMyBLE_CPP::MySqueezies{};

@BrUnO_XaVIeR :…let me tell you something…YOU are my God today! :slight_smile:
I would NEVER solve this without your help. That hint about initialize outside anything in the CPP solved the problem :slight_smile: Thanks again man!

@NilsonLima : That link really helped me fully understand what static means

: Thank you vey much for the AddUnique hint!

You guys are the best!