Calling Interface Functions In C++

I am trying to implement an interaction system via an interface but am having trouble figuring out how to call functions in my interface via C++. I am able to call these interface functions in Blueprints with the message nodes.

Some answers online talk about using Execute_* functions but I can’t find any clear description on how to do this. I have tried casting with Cast<>() and InterfaceCast but these cause my project to crash.

Specifically, what I am trying to do is run a trace to see if there are any actors in front of the player pawn that implement my InteractableInterface. And then I want to be able to call the Interact(…) function on that actor. My InteractableInterface code is shown below.

Any help would be appreciated.
Thanks very much

   UINTERFACE(meta = (CannotImplementInterfaceInBlueprint))
    class UInteractableInterface : public UInterface
    {
    	GENERATED_UINTERFACE_BODY()
    
    };
    
    class IInteractableInterface
    {
    	GENERATED_IINTERFACE_BODY()
    
    public:
    	UFUNCTION(BlueprintCallable, Category = Interact)
    	virtual bool IsInteractable()=0;
    
    	UFUNCTION(BlueprintCallable, Category = Interact)
    	virtual void Interact(AKillablePawn* Instigator)=0;
    };

Try this:

if (YourActor->GetClass()->ImplementsInterface(UInteractableInterface::StaticClass()))
{
  IInteractableInterface::Execute_Interact(YourActor); // This is the Execute_* function. The asterisk means your function name. :)
}

Upon compilation I get Execute_Interact is not a member of IInteractableInterface. I found another error in my code and I was able to cast to IInteractable Interface successfully with Cast < InteractableInterface > (ActorRef);

Thanks for the input

1 Like

I use them extensively, here’s an example:

.h (blueprint callable interface, but implemented in c++)

#pragma once
//this is important for the auto-generated executed functions.
#include "EntityInterface.generated.h"

/** Interface for actors which can be associated with teams */
/** Class needed to support InterfaceCast<IToStringInterface>(Object) */
UINTERFACE(meta = (CannotImplementInterfaceInBlueprint = true))
class UEntityInterface : public UInterface
{
	GENERATED_UINTERFACE_BODY()
};

class IEntityInterface
{
	GENERATED_IINTERFACE_BODY()

	/** returns the owner number of the actor (0=world, otherwise it's a player) */
	UFUNCTION(BlueprintCallable, Category = "ImperoEntities")
	virtual int32 GetOwnerNum() const = 0;

	/** sets the owner number of the actor */
	UFUNCTION(BlueprintCallable, Category = "ImperoEntities")
	virtual void SetOwnerNum(const int32 OwnerNum) = 0;

	/** returns the id number of the actor */
	UFUNCTION(BlueprintCallable, Category = "ImperoEntities")
	virtual int32 GetEntityId() const = 0;

	/** sets the id number of the actor */
	UFUNCTION(BlueprintCallable, Category = "ImperoEntities")
	virtual void SetEntityId(const int32 NewEntityId) = 0;

	/** Remove the given amount from entity's healt (net unsafe) */
	UFUNCTION(BlueprintCallable, Category = "ImperoEntities")
	virtual void ApplyDamage(int32 Amount) = 0;
};

another .h (Blueprint implementable events)

#pragma once

#include "SelectableInterface.generated.h"

/** Interface for actors which can be associated with teams */
/** Class needed to support InterfaceCast<IToStringInterface>(Object) */
UINTERFACE()
class USelectableInterface : public UInterface
{
	GENERATED_UINTERFACE_BODY()
};

class ISelectableInterface
{
	GENERATED_IINTERFACE_BODY()

	/** tries to select actor */
	UFUNCTION(BlueprintImplementableEvent, Category = Selection)
	void OnSelectionGained();

	/** tries to deselect actor */
	UFUNCTION(BlueprintImplementableEvent, Category = Selection)
	void OnSelectionLost();

	UFUNCTION(BlueprintImplementableEvent, Category = Commands)
	bool DoOnTargetEvent(const TScriptInterface<IEntityInterface>& Target, const TEnumAsByte<EJobType::Type>& JobType);
};

.cpp (tip: you can implement more than one interface in only 1 cpp, as u can see)

#include "MyProject.h"
//#include "Interfaces/SelectableInterface.h"
//#include "Interfaces/MultipleSelectableInterface.h"

USelectableInterface::USelectableInterface(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
}

UMultipleSelectableInterface::UMultipleSelectableInterface(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
}

UEntityInterface::UEntityInterface(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
}

and here’s how i call the functions:

//i have multiple targets at once
TArray<IEntityInterface*> Subjects;
//fill the array somehow

//and then call the function on the interface
//note that this function is only declared in the interface,
//the implementation is on Blueprints side

for (IEntityInterface* Subject : Subjects)
{
    ISelectableInterface* s = Cast<ISelectableInterface>(Subject);
    //note that actually i'm using 2 different interfaces
    if (s)
    {
        s->Execute_DoOnTargetEvent(Cast<UObject>(s), Target, Job);
    }
}

Hope this helps you :slight_smile:

I forgot sorry, note that for the execute function you have to provide the UObject context (the Object on which you’re calling the function, as a child of UObject: i used a cast to a generic UObject, but if you already have a pointer of your class type, you can use that directly) as first parameter.

I have this same issue, any updates on the problem?

Execute_Interact was just an example i posted. You need to replace Interact with your function name. For example, if your function name is MyFunction then it should be Execute_MyFunction.

The Execute_* static function only exists on BlueprintImplementable/BlueprintNativeEvent UFUNCTIONs. By using CannotImplementInterfaceInBlueprint, Cast<InteractableInterface> is the correct approach.

8 Likes

I came across this topic when trying to solve a specific UInterface related issue and I thought I might add one important thing to the discussion.

There are actually 2 scenarios in which we’re calling UInterface functions in C++:

  1. When interface is inherited by C++ class
  2. When interface is added in the blueprint Class Settings

Each of those requires different handling in C++ when calling an interface function.
First scenario:

if (Cast<IInterface_MyInterface>(MyActor))
{
	Cast<IInterface_MyInterface>(MyActor)->Execute_MyInterfaceFunction(MyActor);
}

Second scenario (Note UInterface in the if statement and IInterface in the function call!):

if (MyActor->GetClass()->ImplementsInterface(UInterface_MyInterface::StaticClass()))
{
	IInterface_MyInterface::Execute_MyInterfaceFunction(MyActor);
}

Perhaps someone will find this information useful.

6 Likes

The C++ example does not work, at least for me. Some minor alterations are needed:

  1. Remove Execute_
  2. Remove MyActor argument

Like this:

if (Cast<IInterface_MyInterface>(MyActor))
{
	Cast<IInterface_MyInterface>(MyActor)->MyInterfaceFunction();
}

This is supposed to be the correct way to call an interface function:

Method 1:

IInterface_MyInterface::Execute_MyInterfaceFunction(MyActor);

But it doesn’t always work.

Method 2:
So you have to cast to the interface and call the method directly.

Cast<IInterface_MyInterface>(MyActor)->MyInterfaceFunction();

The really annoying part is that the first method can start failing at any time and will fail silently. IOW, it just won’t do anything. The second way will usually give you an error or warning if it doesn’t work.

I’ve had to remove almost all interfaces from being called from C++ because of this. It’s too unreliable.

And you know what’s even worse? I have an interface where SOME of the functions can be called with method 1 while others in the SAME interface can only be called with method 2.

It seems the code looks for existing implementations. And sometimes it finds an implementation that doesn’t exist, calls it and returns immediately. This made me waste TONS of time trying to find out why it wasn’t working. That an interface function is called, but silently ignored was not something I was looking out for. Other times, it won’t find any implementations and will give you a warning that you’re calling it incorrectly.

Finally, we haven’t even talked about how to override these. Sometime you have to override with _Implementation. Sometime, you just override it without _Implementation. And the compiler will complain seemingly randomly. This too can change at any time. Something that worked for a while can suddenly stop working.

When you override with _Implementation, there’s no UFUNCTION. You just make it virtual. But when that doesn’t work and you use the regular function name, it’ll sometimes complain that you need a UFUNCTION or need to remove it (I forget which just now). Anyhow, it sometimes refuses to compile no matter what you do. I’ve been programming for over 35 years. I have rarely seen something this convoluted to get working.

I’ve since made most of my interfaces C++ only with CannotImplementInterfaceInBlueprint. The ones I do call in from C++ and are implemented in BP are implemented ONLY in BP. No C++ implementations of UE interfaces unless they are C++ only. Otherwise, the engine seems to get confused. My guess is that the interaction of BlueprintNativeEvent and interfaces when it comes to C++ overrides don’t mix well.

If this case doesn’t always work, you should really file an issue with Epic. The only time that shouldn’t work is if MyActor doesn’t actually implement the interface (and you should encounter an ensure in that case which is silly). From my own experience with interfaces, I’ve never encountered a case where it failed unexpectedly.

The Cast option will only work with interfaces that use the CannotImplementInterfaceInBlueprint. If it’s blueprint implementable, that cast can produce a nullptr and the call will likely cause a crash.