C++ Parameter that implements Interface

How can I have a C++ function parameter that implements an interface?

C++

I tried that in C++, but it doesn’t compile:

UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void GiveObjectOfInterface(IGameEventListener* EventListener);

Blueprint

In Blueprint I would do that:

Even an array of interface objects is possible:

The interface function would look like this:

// .h file of INTERFACE
virtual void GiveObjectOfInterface(IGameEventListener* EventListener) = 0;

The implementation of the function in a class that implements the interface would look like this:

// .h file of CLASS
virtual void GiveObjectOfInterface(IGameEventListener* EventListener)  override;

// .cpp file of CLASS
void  CLASS::GiveObjectOfInterface(IGameEventListener* EventListener)
{
    // implementation
}

How would I be able to call and implement that in Blueprints?

I want to be able to call/implement that both in C++ and Blueprints…

I believe what you’re looking for is TScriptInterface<IGameEventListener> so either:

void GiveObjectOfInterface(TScriptInterface<IGameEventListener> EventListener);
void GiveObjectOfInterface(const TScriptInterface<IGameEventListener> &EventListener);

This is due to various limitations on interfaces when you allow implementations from blueprint.

The first gives me compile-exception,
but the second seems to work fine:

  1. Doesn’t work:
    • void GiveObjectOfInterface(TScriptInterface<IGameEventListener> EventListener);
  2. Works:
    • void GiveObjectOfInterface(const TScriptInterface<IGameEventListener> &EventListener);

And what about an array of interface objects?

  1. Doesn’t work:
    • void GiveArrayOfInterface(TArray<const TScriptInterface<IGameEventListener>&> EventListeners);

I can’t help much with compile errors if you don’t provide them. Based on a quick search the first one should work just fine. There are numerous functions provided by Epic written exactly that way. Maybe you’re just missing an include or forward declaration or something.

You wouldn’t have the const or & inside the template arguments of TArray. Again you’d either have:

void GiveArrayOfInterface(TArray<TScriptInterface<IGameEventListener>> EventListeners);
void GiveArrayOfInterface(const TArray<TScriptInterface<IGameEventListener>> &EventListeners);

A

UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
void GiveObjectOfInterface(TScriptInterface<IGameEventListener> EventListener);

leads to:

[1/3] Compile AbstractDungeonGameMode.gen.cpp
...\AbstractDungeonGameMode.gen.cpp(30): error C2511: 'void AAbstractDungeonGameMode::GiveObjectOfInterface(const TScriptInterface<IGameEventListener> &)': overloaded member function not found in 'AAbstractDungeonGameMode'
...\AbstractDungeonGameMode.h(14): note: see declaration of 'AAbstractDungeonGameMode'
...\AbstractDungeonGameMode.gen.cpp(33): error C2352: 'UObject::

B

UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
void GiveObjectOfInterface(const TScriptInterface<IGameEventListener> &EventListener);

compiles successfully.

C

UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
void GiveArrayOfInterface(TArray<TScriptInterface<IGameEventListener>> EventListeners);

leads to

[1/3] Compile AbstractDungeonGameMode.gen.cpp
...\AbstractDungeonGameMode.gen.cpp(30): error C2511: 'void AAbstractDungeonGameMode::GiveArrayOfInterface(const TArray<TScriptInterface<IGameEventListener>,FDefaultAllocator> &)': overloaded member function not found in 'AAbstractDungeonGameMode'
...\AbstractDungeonGameMode.h(14): note: see declaration of 'AAbstractDungeonGameMode'
...\AbstractDungeonGameMode.gen.cpp(33): error C2352: 'UObject::FindFunctionChecked': a call of a non-static member function requires an object
...\Object.h(1094): note: see declaration of 'UObject::FindFunctionChecked'

D

UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void GiveArrayOfInterface(const TArray<TScriptInterface<IGameEventListener>> &EventListeners);

compiles successfully

E

UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
const TArray<TScriptInterface<IGameEventListener>> GetArrayOfInterface();

compiles successfully.

Thanks

Solution

Object of Interface

UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
void GiveObjectOfInterface(const TScriptInterface<IGameEventListener> &EventListener);

Array of Interface

UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
void GiveArrayOfInterface(const TArray<TScriptInterface<IGameEventListener>> &EventListeners);

Return Object of Interface

UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
TScriptInterface<IGameEventListener> GetObjectOfInterface();

Return Array of Interface

UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
const TArray<TScriptInterface<IGameEventListener>> GetArrayOfInterface();

Return generic dependend on Interface

Warning: Causes crash when object without interface is added

UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintPure, meta=(DeterminesOutputType="EventType"))
const TArray<TScriptInterface<IGameEventListener>> GetGameEventListeners(TSubclassOf<UGameEventListener> EventType) const;

So before adding something, check if it implements the interface:

I’m pretty sure A & C are only generating compiler errors because they are BlueprintImplementableEvents. Those end up with additional limitations (though not specifically to the TScriptInterface) because of what functionality/features are available in blueprint.

I bet if they were strictly BlueprintCallable and implemented in C++, the signature would compile fine. Though I’m not suggesting that you have to do that. Just making sure that the information is included in this thread for posterity.