UE4 C++ Custom MACRO

Hi @DanM
I Want To Know How To Return An Object From A Macro
Also How To Return Multiple Objects.

I Created This Macro, This Is Creating A Widget And Also Executing Its Member.

#define OPEN_WIDGET(UMGClass, WBP_Class) {UMGClass* UI = CreateWidget<UMGClass>(GetWorld(), WBP_Class);if (UI) UI->SetupWidget();}

But From Here I Want To Return The Widget That I Created “UI” ,

Like,

#define ZERO 0;

auto Number = ZERO;

How Can I Do That??
Also Tell Me Proper Way To Use Brackets Inside MACRO.


And Do I Need To Check #ifndef ? if Yes Then Why?

#ifndef OPEN_WIDGET
	#define OPEN_WIDGET
#endif

Macro’s are just simple text replacement. You don’t “return” anything.
This is an example of what that would expand to
Compiler Explorer

Macros are best avoided and this can easily be a template instead

template<class UMGClass>
UMGClass* OpenWidget(TSubclassOf<UUserWidget> WBP_Class)
{
    UMGClass* UI = CreateWidget<UMGClass>(GetWorld(), WBP_Class);
    if (UI) 
    {
        UI->SetupWidget();
    }
    return UI; 
}

// Used like
UUserWidget* Thing = OpenWidget<UUserWidget>(WBP_MyWidget);
1 Like

Thanks For The Example Of Template :+1:t2:.

You Said MACRO Returns Nothing, But
How TEXT MACRO Returns?

const wchar_t* Var = TEXT("Hello");

And Also If I Open Blueprint And Create MACRO Then I Can Return Multiple Things There, Then Why Not In C++?? :roll_eyes:

It doesn’t “return”. On Windows the TEXT macro prepends an L and that code would expand to

const wchar_t* Var = L"Hello";
1 Like

1.And What About Blueprint MACRO?? How It Is Returning Multiple??

2.How To Expose A Template To Blueprint?

	template<class T>
	UFUNCTION(BlueprintCallable) // Not Working
		T* TestTemplate()
	{
		return nullptr;
	};
  1. They’re not the same only similar. If you removed the brackets in your original you could continue to use UI.
    OPEN_WIDGET(UUserWidget, WBP_MyWidget)
    
    Would expand to (though I added some formatting)
    UUserWidget* UI = CreateWidget<UUserWidget>(GetWorld(), WBP_MyWidget);
    if (UI) 
        UI->SetupWidget();
    
    You could then technically use UI after that e.g.
    OPEN_WIDGET(UUserWidget, WBP_MyWidget) 
    UI->Foo();
    
    Because that would expand to
    UUserWidget* UI = CreateWidget<UUserWidget>(GetWorld(), WBP_MyWidget);
    if (UI) 
        UI->SetupWidget();
    UI->Foo();
    
    Demo: https://godbolt.org/z/esWvfv4rc
  2. Unfortunately function templates are not supported with UFUNCTION. Someone has a PR that adds support for it here https://github.com/EpicGames/UnrealEngine/pull/6902 (you’ll need to be signed in and have your account linked in order to see). Hopefully it will be in a future version.
    You would need to specify the types you want it to work with though from the example code
    UFUNCTION(BlueprintCallable, TemplatedTypes = (int32, float, FColor, FLinearColor))
    template<typename T>
    void MyTest(T Left, T Right);
    
1 Like

Thats It!! :ben:
Thats I Wanted To Do,
But How To Use Multiple Variable From This MACRO

Suppose :

OPEN_WIDGET(UUserWidget, WBP_MyWidget) UUserWidget* UI = CreateWidget<UUserWidget>(GetWorld(), WBP_MyWidget);if (UI) UI->SetupWidget(); float Ratio = UI->Foo();

I Am Unable To Access Ratio Variable.

I highly suggest you don’t use a macro for what you’re trying to do. Macros are best avoided.
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-macros2

What are you trying to do?

1 Like

Oh Ok, Can MACRO Crash My Game?

I Am Using MACRO Because There Are Several Location And Several Code Files Where I Wrote Same Line Of Code, So Basically Instead Of Writing Same Line Of Code I Used MACRO, It Successed,

From:

TearDown(); // Remove From Parent Current Widget
UUMGBase* StoreUI = CreateWidget<UUMGBase>(GetWorld(), StoreUIClass);
if (!StoreUI) return;
StoreUI->SetupWidget();

To

OPEN_WIDGET_UI(false, UUMGBase, StoreUIClass);

Tell Me Is It Safe?

A macro is just a dumb text replacement that happens before compilation happens. It would only cause a crash if the expanded code would crash.

They’re best avoid precisely because they’re just a dumb text replacement. You can’t debug them, the compiler can’t tell you if you messed up as it will only see what the macro expanded to, etc.

I suggest you read the answer for this SO post

c++ - Why are preprocessor macros evil and what are the alternatives? - Stack Overflow

Well if you have a base class that has SetupWidget then you can just use that base class and make it a normal function

UUMGBase* Foo::Setup(TSubclassOf<UUMGBase> StoreUIClass)
{
    UUMGBase* StoreUI = CreateWidget<UUMGBase>(GetWorld(), StoreUIClass);
    if (StoreUI)
        StoreUI->SetupWidget();
    return StoreUI;
}

void Foo::Bar()
{
    UUMGBase* Thing = Setup(UIClass);
    if (Thing)
    {
        //use Thing
    }
}

Edit: Oh and you can do what the engine does and provide a template version that calls the other i.e. if you need a derived type you would do

UDerivedUMG* Thing = Cast<UDerivedUMG>(Setup(UIClass));
if (Thing)
{
    // use Thing
}

which is too much typing for our delicate hands. If you create a template that does

template<class T>
T* Setup(Blah)
{
    return Cast<T>(Setup(Blah));
}

You can then just write

UDerivedUMG* Thing = Setup<UDerivedUMG>(UIClass);
if (Thing)
{
    // use Thing
}

So this would just be syntactic sugar for C++ code. The first should still work for BP. This is actually what the templated versions of GetController, GetPawn, GetOwner et al. do

1 Like

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