[C++] Get Delegates in Interface?

Good day everyone!

I want that my Interface-inherited classes can have Delegates. Since Interface can’t have variables, I found a solution of that in 's post:

virtual FYourDataStruct& GetDataStruct() = 0;

But I didn’t managed it to work. Here is my code:

EnergyDeviceInterface.h:

DECLARE_DYNAMIC_DELEGATE_OneParam(FEnergyDeviceDelegate, EEnergyDeviceEnum, DeviceType);

UINTERFACE()
class UEnergyDeviceInterface : public UInterface
{
	GENERATED_BODY()
};


class IEnergyDeviceInterface
{
	GENERATED_BODY()

public:
	virtual FEnergyDeviceDelegate& GetEnergyDisableDelegate() = 0;
}

GunComponent.h:

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent, DisplayName="GunComponent") )
class UGunComponent : public UActorComponent, public IEnergyDeviceInterface
{
	GENERATED_BODY()

public: 
	UPROPERTY()
	FEnergyDeviceDelegate DisableEnergy;

	virtual FEnergyDeviceDelegate& GetEnergyDisableDelegate() override;
}

GunComponent.cpp:

FEnergyDeviceDelegate& UGunComponent::GetEnergyDisableDelegate()
{
	return DisableEnergy;
}

Everything compiles well until I’m trying to call that GetEnergyDisableDelegate() function:

FEnergyDeviceDelegate& DeviceDelegate = IEnergyDeviceInterface::Execute_GetEnergyDisableDelegate(Device);

Where Device - is the pointer on the UGunComponent (and I have checked if Device implements that interface). But I’m getting that kind of error:

C2039 ‘Execute_GetEnergyDisableDelegate’: is not a member of ‘IEnergyDeviceInterface’

I made some researches I and found an info, that Unreal macro-system doesn’t support pure virtual functions and I need to use PURE_VIRTUAL with some parameters in it. But since it’s a delegate, I can’t pass a nullptr on it.

How can I make it work?

You need to put UFUNCTION() on function deceleration of interface, otherwise UHT will ignore it and do add function to reflection system as well won’t generate Execute_* function for that function, thats why it say it’s not declared.

If UHT gives you any error then it means what you doing is not supported by UE4 reflection system. In that case you can make blueprint static function else where.

Note that if you use that interface only in C++ you don’t need to use Execute_* function as well as UFUNCTION() and just call function directly as all you need to do in C++ is add parent to class to implement interface, Execute_ is only to forward function call to Blueprint system as UE4 have no chance to intercept normal C++ function calls. It’s exact same issue as with events.

Thanks for the answer.

If I put UFUNCTION() on function declaration of interface, I’m getting the same error: “‘Execute_GetEnergyDisableDelegate’ is not a member of IEnergyDeviceInterface”. That means I’m not supposed to make it work via Execute_*, right?

No what im saying is if you UHT error then it means what you doing is not supported by reflection system. Execute_ should work with UHT passed your deceleration, if it processed at all. And that you can skip all that and just call interface function direclly if you plan to use this interface only in C++. What you getting is compiler error, which means UHT didnt generate code for the interface some reason

Did you tried rebuilding?

As you’ve said, I need to give up on trying to make it work with UFUNCTION() and stick with only C++. Thanks!

If anyone will be looking for straight code solution, here is it:

EnergyDeviceInterface.h:

UINTERFACE()
class UEnergyDeviceInterface : public UInterface
{
	GENERATED_BODY()
};

class STARSHIPS_API IEnergyDeviceInterface
{
	GENERATED_BODY()

public:
	virtual FEnergyDeviceDelegate* GetEnergyDisableDelegate() = 0;
}

GunComponent.h:

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent, DisplayName="GunComponent") )
 class UGunComponent : public UActorComponent, public IEnergyDeviceInterface
 {
     GENERATED_BODY()
 
 public: 
     UPROPERTY()
     FEnergyDeviceDelegate DisableEnergy;
 
     virtual FEnergyDeviceDelegate* GetEnergyDisableDelegate() override;
 }

GunComponent.cpp:

FEnergyDeviceDelegate* UGunComponent::GetEnergyDisableDelegate()
{
	return &DisableEnergy;
}

and to call it just simply:

IEnergyDeviceInterface* energyDeviceInterface = Cast<IEnergyDeviceInterface>(Device);
FEnergyDeviceDelegate* DeviceDelegate = energyDeviceInterface->GetEnergyDisableDelegate();
if (DeviceDelegate)
		(*DeviceDelegate).AddDynamic(this, &UEnergyComponent::DisableDevice);
1 Like