Save char* from FString to a variable

Hello Devs,

I’m trying to get a *char from FString and store it in a class variable. I know TCHAR_TO_ANSI and StringCast<ANSICHAR> methods, but *char created by those methods lives only in function scope. I want to get *char, save it to a variable and use it later in another function.

Example (TestChar is const char* variable)

void UMySubsystem::SetTestChar(FString TestString)
{
	auto TestCharConvert = StringCast<ANSICHAR>(*TestString);
	TestChar = TestCharConvert.Get();

	FString NewString(TestChar);
	UE_LOG(LogTemp, Warning, TEXT("Set Test char to: %s"), *NewString);
}

void UMySubsystem::PrintTestChar()
{
	FString TestString(TestChar);

	UE_LOG(LogTemp, Warning, TEXT("Test char: %s"), *TestString);
}

Is giving results as expected:
image

So the question is how to save the actual memory that the *char is pointing to?
Thanks in advance!

I also tried these 2 methods, but both of them crash. Maybe you know what I’m doing wrong here:

This is inside previously mentioned “SetTestChar” function:

FMemory::Memcpy(TestChar, TCHAR_TO_ANSI(*TestString), TestString.Len());
	
memcpy_s(TestChar, TestString.Len(),  TCHAR_TO_ANSI(*TestString), TestString.Len());

Why are you trying to do this in the first place? You’re just causing yourself headaches and future pain this way. In vanilla C++, you’d default to using std::string. In Unreal if you want to keep it around you’d just copy it into another FString.

Of course your memcpys are going to crash, TestChar doesn’t actually point to any memory that you’re allowed to write to. You’d have to manually manage memory for the string if you want to do this, but it’s not advisable to do that which is why I suggested just sticking with FString.

Hi @MagForceSeven and thanks for your answer. I’m writing Unreal wrapper on top of an old SDK written in C. So I want developer to provide everything in FStrings, but I have to convert all of them to char*. In most cases StringCast<ANSICHAR> is enough, but for some cases I need to have char* that will live longer than in function scope.

For example when initializing SDK I need to provide access keys in char*, but they have to be valid for the whole time (SDK doesn’t copy them) - that’s why I want to save FString key provided in plugin settings to a subsystem char* variable .

Ohh I see, so how would you make TestChar to point to memory that it could write to before memcpy?

The problem with your original code is that your doing the StringCast on a temporary function variable. That’s why your “Set” log works but later the “Test” log fails, because the variable that you cast from no longer exists.

Your best option is for you to keep storing it as an FString (so you’d copy TestString into a member variable of the same type) and then do the string cast when you need to call that SDK. As long as you don’t change your FString and your subsystem isn’t shutdown the pointer might remain valid. I say “might” only because I’m not familiar with the implementation details of StringCast.

If the pointer doesn’t remain valid, you’d have to do your memcpy which means either: TestChar needs to be a character array (char ) of a size you know is always big enough for your SDK access keys or you’ll have to use new & delete to dynamically size a character array that you can copy into.

1 Like

This unfortunately didn’t work, even if I store FString as class variable and StringCast from it, TestChar is still empty after function scope.

Thank you very much for your help that indeed worked. I used fixed size for char and then memcpy worked fine.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.