[C++] I want to output FString by BluePrint and get it by PrintString

Nice to meet you.
This is my first question and I’m sorry if I don’t have enough information.

I want to do Http Request in C++ and get the value from DB (when I enter ID, PlayerName of the same ID in DB will be returned), but I want to get the returned PlayerName by Print String using BluePrint.

//h
UFUNCTION(BlueprintCallable, Category = "Http")
void MyMethod(const FString& id, FString& PlayerName);

//CPP
void AMyActor::MyMethod (const FString& id, FString& PlayerName)
 {
 ~~
 GEngine->AddOnScreenDebugMessage(1, 2.f, FColor::Red, PlayerName);
 }

I’m getting a normal value in the debug message, but the output of the node contains no information.

How can I get this PlayerName to print out as a string with BluePrint? I would appreciate your help.

I’m new to working with C++.
This is a rudimentary question, but I’d appreciate an answer.

// UE4 , 4.25.4

If you’re working with getting information from a database are you performing everything asynchronously? If so, that would mean you have a bit of a race condition where the database might still be returning with an answer by the time the blueprint node goes to the PrintString node (meaning PlayerName would be null).

I’m not sure if the code you’ve sent is everything you have, or if you’ve left out the database stuff. From what I can tell with the snippet you shared, it doesn’t look like anything is happening to PlayerName.

Thanks for the answer!

Due to lack of knowledge, I cannot determine if the asynchronous connection is enabled.
However, I think it’s probably in an asynchronous state as you mentioned.
I’ve tried to improve it, but I just get more errors.

The process flow is as follows. //cpp


1… void MyMethod (const FString& id, FString& PlayerName);

2… Creation of Json data to store id.

3… Json writing out to OutputString.

4… Create Http Request.

5… Define and request a URL and other information

6… Bind (void) on completion of a process request.

7… Display a debug message → This is being retrieved successfully.

---- (void)

1… Deserialize the Json object.

2… Get the id and PlayerName values from Json.
FString id = JsonObject->GetStringField(“id”);
FString pn = JsonObject->GetStringField(“PlayerName”);

Three… return MyMethod (id,pn)

No problem! I’m not super well-versed on making HTTP requests using UE4, but I’d like to see if I can help!

What API/framework are you using for the HTTP requests? Also, when you say “Bind (void) on completion…” do you mean you’re binding a void-return-type function as a callback for when the HTTP request receives a response?

Thank you for your kindness!


6… Bind (void) on completion of a process request.

→ Request->OnProcessRequestComplete().BindUObject(this, &AMyActor::OnResponseReceived);

-----



… ‘POST’ to ‘Login.php’ that I have on my server in Http

… Deserializing POSTed JSON in PHP

… Connect to the DB(MySQL) with PHP and search for PlayerName using the ID

… Store ID and PlayerName in JSON in PHP

… JSON back to C++



----- …

// The above work has been completed without any problems.

// The debug message reflects the ID and PlayerName.

However, the information received from the DB is displayed in the debug message, but it seems to be acquired continuously and the display does not disappear.

I think what I need to do is to clear the “I might still get something from the DB” race condition, but I don’t know how…

How about the following methods?

A. like BluePrint’s DoOnce, it executes the process only once.

B. stop continuous processing by some means.

Is there any information that is missing?

Haha it’s no problem, I’m happy to help!

Okay I might see the issue! I was wrong about the race condition: the OnResponseReceived() method should handle that.

I have two notes:

1: At the top of OnResponseReceived(), before you process any of the data, I’d recommend checking if bWasSuccessful is true, and if not then print the response code to the console. Something like this:

if (!bWasSuccessful) 
{
    UE_LOG(LogTemp,Warning,TEXT("HTTP request failed. Response code: %d"), Response->GetResponseCode());
    return;
}

That way you’ll know if the response was not successful, and it won’t try to process anything unnecessarily. There’s always a chance that something could go wrong during the request, and this will help debug any issues there.

2: Are you calling the MyMethod node in Blueprints, or are you overriding it? Because I think that might be the issue.

If you’re calling it in Blueprints (e.g. attaching the white “execute” line to a MyMethod node), then that means you’re calling a new version of MyMethod, and not the one called in OnResponseReceived() (meaning it has no information).

What I think you might want – and forgive me if I’m mistaken – is to override it so you can extend the functionality of it in Blueprints. If that’s the case, you’d need to add the BlueprintNativeEvent specifier to the UFUNCTION() macro.

Also, you probably don’t want PlayerName to be returned in Blueprints, but rather be a parameter that’s being passed in (the syntax for that trips me up all the time).

Your function definition should probably look something like this:

 UFUNCTION(BlueprintNativeEvent, Category = "Http")
 void MyMethod(const FString& id, const FString& PlayerName);

Edit: I removed BlueprintCallable to avoid confusion. You probably don’t want to be calling this method in Blueprints, since it’s being called when OnResponseReceived() finishes.

Edit 2: I made a mistake: It should not be BlueprintImplementableEvent, but rather BlueprintNativeEvent in this case (because we have a C++ definition). For anyone who may be reading this after-the-fact, you also want to add “_Implementation” to the end of the function in the *.cpp file, like the following:

void AMyActor::MyMethod_Implementation(const FString& id, const FString& PlayerName)

However, you do not want to add “_Implementation” in the header file. Intellisense will get angry, but it’s okay, it should still compile.

Then, in Blueprints, you can override MyMethod by clicking on “Override” next to the “Functions” bar on the left, like so:

And when you click on that, it should generate a new event on the Event Graph for you. When MyMethod is called on this Blueprint class (be it from C++ or Blueprints), it will now call this version of MyMethod, meaning you can add whatever logic you want.

One thing to note is that you should almost always be sure to include a call to the parent version of the method, otherwise you might accidentally completely override what you wrote in C++.

To do that, just right-click the Event node and do “Add call to Parent Function”.

Finally, you can start hooking up your nodes. I think you’re looking to do something like this:

Let me know if I got something wrong anywhere! I’d be happy to continue to help you debug this problem!

I see you as a god as well.

I removed BlueprintCallable as instructed and added a BlueprintImplementableEvent.
I’ve also added const to the PlayerName.

However, an error message appeared instead, saying LNK2005.

It says that it is already defined in “MyMethod.gen.cpp.obj” in the \Epic GamesProjects\MyProject\IntermediateProjectFiles.

I couldn’t get to that file…

Haha far from a “god”, I wouldn’t even say I’m an expert programmer by any means!

Linker errors are usually a bit funky to deal with. A lot of times they won’t point to the actual issue, so it takes a bit of figuring out.

As for this one, I think it’s a bit of a mistake on my part. BlueprintImplementableEvents aren’t supposed to be defined in C++. It’s sort of like an abstract function. What I should have told you was BlueprintNativeEvent. BlueprintNativeEvents can have a C++ definition, and can be overridden in Blueprints.

  UFUNCTION(BlueprintNativeEvent, Category = "Http")
  void MyMethod(const FString& id, const FString& PlayerName);

Then, in your MyActor.cpp file, where you have AMyActor::MyMethod defined, change it from

void AMyActor::MyMethod(const FString& id, const FString& PlayerName)

to the following:

void AMyActor::MyMethod_Implementation(const FString& id, const FString& PlayerName)

Again, VS intellisense will give you a funky red-line and tell you “MyMethod_Implementation” does not exist, and might even yell at you in the header file too saying that “MyMethod is not defined,” but once you compile it should figure it out.

BlueprintNativeEvents have to have that weird “_Implementation” suffix when you define them in C++.

For more information on BlueprintNativeEvents and BlueprintImplementableEvents, you can check out this page on the UE4 documentation. Also, the community wiki has a page on BlueprintNativeEvents and BlueprintImplementableEvents.

Well I’m not sure why, but it seems like UE4 mods have eaten up my answer… (It said it was under review for some reason), so I guess I have to post it again haha.

Haha, far from a “god”, I wouldn’t even consider myself an expert programmer!

This was actually my mistake. Instead of BlueprintImplementableEvent, I should have told you BlueprintNativeEvent. BlueprintImplementableEvent is when you want it to act like a virtual function (no C++ definition), BlueprintNativeEvent is used when you have a C++ definition, but you still want to override it in Blueprints.

After you change that in the header file, go to the MyActor.cpp file and change the function from this

void AMyActor::MyMethod (const FString& id, const FString& PlayerName)

to this

void AMyActor::MyMethod_Implementation (const FString& id, const FString& PlayerName)

For some reason BlueprintNativeEvents need to have that “_Implementation” suffix. VS Intellisense will appear angry with you and say there’s no function declaration or something, but it should compile.

I had linked pages about BlueprintNativeEvents and BlueprintImplementableEvents from UE4’s own documentation and the community wiki, so maybe that’s why it got flagged as “needing review”…

Hope that helps!

Thank you for being so kind.

I’ve been trying since you answered and until now, I’ve been unable to pass the PlayerName to PrintString.

BlueprintCallable,BlueprintPure,BlueprintImplementableEvent,BlueprintNativeEvent…all of which I’ve tried and the compilation worked fine.

In the future I wanted it to work so that I could pull up information like PlayerName and PlayerStatus and SpawnPoint, etc. with just the id and password input.

Thanks for being so generous. I’m very happy with it.

No problem! I’m happy I could help in any way!

Yeah you should be able to pass those as parameters in the future if you wanted to get that information. Like so:

UFUNCTION(BlueprintNativeEvent, Category = "Http")
void MyMethod(const FString& id, const FString& PlayerName, const FString& PlayerStatus, const FVector& PlayerSpawnPoint);

And just pass it those values when you call MyMethod in OnResponseReceived(). You could also make a specific method for each piece of data you want to retrieve.

If you’re still getting any issues with it, feel free to let me know! I’d be happy to help!