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
https://godbolt.org/z/er7Yb8vvc

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

https://stackoverflow.com/questions/14041453/why-are-preprocessor-macros-evil-and-what-are-the-alternatives

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.

Privacy & Terms