Third Party plugin (C++) std::vector return workaround

I am trying to write a plugin (using third party code in a DLL that I have made) that returns results in a std::vector. This is obviously not possible directly, and causes a memory problem and a crash.

Advice elsewhere explains that UE wants me to use a TArray rather than vector, and that the std:: types should be avoided. A very old thread suggested that ‘you should first create wrapper classes in UObject environment that will convert standard types to UE4 types’.

I am not very sure of what this means. Should I create a UObject C++ Class, with functions that convert std::vector to TArray? If so, how can I still use std::vector without causing crashes? How should the function in the DLL return the vector?

The trick is to use an intermediary DLL which exposes a Unreal-compatible API outwards, but uses the STL API on the insides.

Typically, you’ll define a C-like API with a bunch of functions and struct pointers, and then implement that API on top of the C++/STL by using delegation, and then in turn include and call this C API from Unreal.

Thank you. How is this done?

why is it crashing, It should not, did you import all the things you need , iostream, std standard library etc.

You can use the Vector array in unreal without problems. It’s problem is of course maybe you are telling it stuff that it cannot do, Vector array does not accept math vector operation by default.

It’s not for vectors in general, the name is a hack. Has no support for simple axis [0]1][2] nor any other vector math operation, maybe you are telling it to do what it can’t do or have broken code .

1 Like

Thanks Gigik. It appears to be crashing when the std::vector goes out of scope. My plugin is a UBlueprintFunctionLibrary, which uses a function in a DLL with 3rd party libraries.

I’ve tried every return method I can think of. But ultimately, they always crash with errors of this nature:

Exception thrown at 0x00007FFF2B1E7ACB (UnrealEditor-Core.dll) in UnrealEditor.exe: 0xC0000005: Access violation reading location […]

Other discussions here seem to suggest that this is because std::vector doesn’t work well with UE’s garbage collection.

Blue prints I have no idea yea.
So the vector array is in the third party software ?
How does it go out of scope, it’s dynamic alocated to be unlimited, shrinks and expands auto.

Your error is rather an invalid memory location, meaning it cannot find what it’s looking inside there.

You created a vector array with a pointer system ?

1 Like

[quote=“GigiK-K-K, post:6, topic:1181735”]
So the vector array is in the third party software ?[/quote]

Not quite, it’s in my implementation. I am returning vertices and faces that are produced using third party libraries (simple geometry). In fact, I haven’t even fully implemented the libraries yet – I’m just filling the vectors up with meaningless floats (for the verts) and ints (face indexes) to try to get them back into UE, where I print them to the screen to test the communication with the plugin.

You created a vector array with a pointer system ?[/quote]

(If I understand…) I have tried passing by return value and reference and pointer to Vector created in my plugin, taking care with new… delete… Sometimes it works for one or two cycles of the game, sometimes as many as twenty. Then crashes.

How does it go out of scope, it’s dynamic alocated to be unlimited, shrinks and expands auto.

I mean it occurs just after the end of my plugin’s function.

Your error is rather an invalid memory location, meaning it cannot find what it’s looking inside there.

Yes, but it works until the end of the function, even if I’ve used new… delete… properly (or any other method.

it’s for sure your memory alocated pointer for the vector array.

You did something like

float * myarray;
then:

vector < float > myarray[Array_size];

or maybe per haps you should try:

vector < float >myarray* = new vector < float > [Array_size];

Just curios about this array, are you using the push back function after you created the array with a pointer.

Maybe you should try inserting data in it with “->”
I have no idea how this array works with a pointer and I’m basicly in interest of that.
Maybe you have to have a limit, try setting a limit at the end of the array, maybe set size of array, orrrrrrrr… I 've seen it in linked lists, they use some kind of end node to say the list ends there.

Inserting like this with pointer system:
myarray->push_back(value_here);
It should work if it’s with a pointer and maybe your problems go’s away.
Maybe your flaw is not using the pointer system and you are using regular push back funct, or just :

array[index_whatever] = vectors values, values etc ;

I bet that may be your problem maybe. If you created it with a pointer then use → to insert into it

1 Like

Thanks for your help, GigiK!

More like this:

In my DLL.h:

KBW_DLL_API struct K_Vertex {
    float x = 0;
    float y = 0;
    float z = 0;
};

KBW_DLL_API struct K_Face {
    int a = 0;
    int b = 0;
    int c = 0;
};

in my plugin:

FString UKBW_BP::getGeom() {
	std::vector<K_Face>* kf = new std::vector<K_Face>;
	std::vector<K_Vertex>* kv = new std::vector<K_Vertex>;
	getGeometryP(kv, kf); // THIS IS CALL TO FUNCTION IN MY DLL
        FString output = "RESULT:\n";
 
	for (int vX = 0; vX < kv->size(); vX++) {
	    output.Append(	"\nV: " + 
						FString::SanitizeFloat(kv->at(vX).x) +
						", " + 
						FString::SanitizeFloat(kv->at(vX).y) +
						", " + 
						FString::SanitizeFloat(kv->at(vX).z)
		);
	}
	
	for (int fX = 0; fX < kf->size(); fX++) {
	    output.Append(	"\nF: " +
						FString::FromInt(kf->at(fX).a) +
						", " +
						FString::FromInt(kf->at(fX).b) +
						", " +
						FString::FromInt(kf->at(fX).c)
		);
	}
  
    output.Append("\n");
    delete kv;
    delete kf;
    return output;
}

In the DLL.cpp:

void getGeometryP(std::vector<K_Vertex>* KBW_vertices, std::vector<K_Face>* KBW_faces){ 

    K_Vertex v;
    v.x = 0.1f;
    v.y = 0.2f;
    v.z = 0.3f;
  
    K_Face f;
    f.a = 0;
    f.b = 1;
    f.c = 2;
  
    for(int V = 0; V < 100; V++) {
        KBW_vertices->push_back(v);
        KBW_faces->push_back(f);
    }
}

This ran fine 10 times out of 11 the first time, then it crashed on the 11th in the Editor. I built & run again, and it ran once and then crashed on the second time.

Yes dude, you are using the → to insert.

I would try to set a size for it, and then don’t go all the way on the loop

 for(int V = 0; V < 99; V++) {
        KBW_vertices->push_back(v);
        KBW_faces->push_back(f);
    }

and set the array to 100, manual set it, it should set even if it’s dynamic.
This is not a fix of course, but just to see if you get away with it.
Maybe you can say it’s nullptr and maybe this will fix your problem after you get everything inside the array

you would have to find a way to say array = nullptr after you do everything and get the results

Simply dealocate everything after you are done.
Each time it runs the function at the end it dealocates.

Setting it manual

std::vector<K_Face>* kf = new std::vector<K_Face>[100];
or maybe
std::vector<K_Face>* kf = new std::vector<K_Face>(100);

As nullptr gos’ Says here:

In C++, the null pointer, often written as “nullptr”, can b
ze defined as a keyword that is used to represent the absence of a memory address.

and…
It is mainly used to show that a pointer is temporarily not pointing at any legitimate object or element.

so when you finish sort of type* pointer_var = nullptr;
It dealocates the address from associating or pointing to anything.

1 Like

EDIT: Unfortunately, I was wrong. This isn’t the solution. It’s more stable, but still crashes.


Win! :grinning:

I set the size of the std::vector in the calling function. No crash.

This doesn’t fix it, as you said, as the calling function doesn’t know how big the vector needs to be. And I couldn’t quite follow your suggestion about nullptr precisely.

However, I realised that what you’re getting at is that std::vector<> doesn’t really want to be std::vector<>* so in the DLL function I do:

KBW_vertices->resize(100);
KBW_faces->resize(100);

and then in the calling function, I do:

kv->clear();
kf->clear();
delete kv;
delete kf;

This also runs without crash. I gather that making the std::vector reduces its functionality.

Many thanks for your help! Now I can get on with my game!

you can use the ()size function with -1 minus one on the loop, this could be a workaround. This way you always know how big the array is and you just write it with minus one on the loop.

 for(int V = 0; V < size(array_name) - 1; V++) {     Etc }

There…yaa go.

For example

#include <iostream>

using namespace std;

int main()
{
    
    
int myNumbers[4] = {1,2,3,4};

for (int i = 0; i < sizeof(myNumbers) / sizeof(int) -1; i++) 
{  
    
    cout<<myNumbers[i];

}


    return 0;
}

This works
Output : 1.2…3

KBW_vertices->resize(var_from_within_loop);
KBW_faces->resize(var_from_within_loop);

As for those you can have a workaround as well, you’d have to have a way to set things as you are inserting them, so your size of array should be controled by a variable that reajusts it’s self each count, each count it will hold the new number of the size of the array.

This can also be done with size() sizeof() funct.

It will read current size of array as the loop is revolving and each time return a value to some function that overides the size of the array with the value from the current size.

For ex this code.

Each time the size of the array is stored inside the variable, changing , as the array expands each time the size the array is maybe modified with the variable.

So you set it every count as it grows, maybe with + 1 position to have an extra position or maybe since it’s dynamic it’s not a problem.

In this case each count produced a "4 " since the array here is manual and all values are defined already, so it’s not growing and not of vector type.