C++ Interfaces Changed in 4.13.2... No documentation?

Just spent about 20 minutes trying to figure this one out. Please note that the ONLY different when compiling my project before and after this error, was upgrading to 4.13.2

UInterfaces now use GENERATED_BODY() and not GENERATED_UINTERFACE_BODY(), which causes problems if you have an existing UInterface of your own. From my project:



UINTERFACE()
class BZGAME_API UBZGame_GameObjectInterface : public UInterface
{
	GENERATED_UINTERFACE_BODY()
};


Becomes:



UINTERFACE()
class BZGAME_API UBZGame_GameObjectInterface : public UInterface
{
	GENERATED_BODY()
};


If you don’t do this, you’ll get an Unresolved Externals error. Here’s mine:



Creating library F:\Depot\BZGame_Main\Intermediate\Build\Win64\UE4Editor\DebugGame\UE4Editor-BZGame-Win64-DebugGame.lib and object F:\Depot\BZGame_Main\Intermediate\Build\Win64\UE4Editor\DebugGame\UE4Editor-BZGame-Win64-DebugGame.exp
2>BZGame.h.obj : error LNK2019: unresolved external symbol "public: __cdecl UBZGame_GameObjectInterface::UBZGame_GameObjectInterface(class FObjectInitializer const &)" (??0UBZGame_GameObjectInterface@@QEAA@AEBVFObjectInitializer@@@Z) referenced in function "public: void __cdecl UBZGame_GameObjectInterface::`default constructor closure'(void)" (??_FUBZGame_GameObjectInterface@@QEAAXXZ)
2>BZGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: __cdecl UBZGame_GameObjectInterface::UBZGame_GameObjectInterface(class FObjectInitializer const &)" (??0UBZGame_GameObjectInterface@@QEAA@AEBVFObjectInitializer@@@Z)
2>F:\Depot\BZGame_Main\Binaries\Win64\UE4Editor-BZGame-Win64-DebugGame.dll : fatal error LNK1120: 1 unresolved externals
2>ERROR : UBT error : Failed to produce item: F:\Depot\BZGame_Main\Binaries\Win64\UE4Editor-BZGame-Win64-DebugGame.dll


No idea how this substantial change slipped through without anyone noticing… I can’t be the only one hitting this wall right now?

Umm, IIRC it should be GENERATED_UINTERFACE_BODY, not GENERATED_UCLASS_BODY

Yep, correct… GENERATED_UINTERFACE_BODY() for the U : UInterface class, and GENERATED_IINTERFACE_BODY() for the I class.

This has not changed with 4.13.2.

So ive checked, i was using GENERATED_UINTERFACE_BODY all in 4.12 you cannot compile with neither GENERATED_UCLASS_BODY nor GENERATED_BODY, so i dont know how your code was working before and now.

Epic really haven’t done a good job of conveying this, but all of these macros were superseded by GENERATED_BODY multiple engine versions ago. You should be using it in all cases, UCLASS, USTRUCT, UINTERFACE and the accompanying interface class.

I think the only reason the old ones haven’t been phased out yet (though maybe it has changed in 4.13.2?) is that replacing all instances in the engine is a big job. There are minor differences which means you can’t always just search and replace without making some other changes. The old version for classes declared a constructor that you needed to implement yourself for example, but would need to remove or redeclare if you switched to the newer macro.

no, it doesnt compile with GENERATED_BODY() for me in 4.12.

Jamsh just used incorrect macro before - UCLASS instead of UINTERFACE. You still can use legacy UCLASS/USTRUCT and GENERATED_BODY as well.

However you’re incorrect about interfaces - it’s more complicated. If you want to use it both and in C++ and BP - you have to create 2 classes with GENERATED_UINTERFACE_BODY and GENERATED_IINTERFACE_BODY macros
And this is not outdated/superseded workflow. With GENERATED_BODY it can’t tell the difference between the two and if you create new Unreal interface via Create C++ class then you will get same 2 UINTERFACE_BODY and IINTERFACE_BODY macros

Like I said, they cannot always be updated without needing to adjust something else.

Yeah I was wondering if that was just a typo in his post, since I wouldn’t have expected that to compile previously either.

I wasn’t saying that you don’t need the two classes for an interface, just that they should both now be using GENERATED_BODY. I don’t know what you mean by “it can’t tell the difference”. Here is some code from my marketplace charts plugin, which has been up since 4.11 and was written well before that. It works fine with both C++ and BP.



UINTERFACE(Blueprintable, MinimalAPI)
class UKantanCartesianDatasourceInterface : public UInterface
{
	GENERATED_BODY()
};


class KANTANCHARTSDATASOURCE_API IKantanCartesianDatasourceInterface
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Cartesian Datasource")
	int32 GetNumSeries() const;

	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Cartesian Datasource")
	FName GetSeriesId(int32 CatIdx) const;
	
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Cartesian Datasource")
	FText GetSeriesName(int32 SeriesIdx) const;

	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Cartesian Datasource")
	TArray< FKantanCartesianDatapoint > GetSeriesDatapoints(int32 SeriesIdx) const;
};


Okay, my bad!

Before posting I tried to create interface with GENERATED_BODY, but got errors like IMyInterface already have a body and I instantly assumed it has something to do with GENERATED_BODY, however, the problem was in constructor definition in CPP file which was auto generated and I did not even knew it is there :smiley:

Thank you, now my interfaces will be a bit cleaner :slight_smile:

Yeah I think that was probably one of the reasons they changed it. The way the old macros internally declared stuff like a constructor which you had to define was confusing. The new ones have less hidden effects which is better, only problem is it can lead to confusing compiler errors when trying to make the switch.

So now we can delete cpp file?

I’m guessing you’re using the AddClass/Interface option in the editor that generates code for you? I don’t use it so I’m not certain what it generates, but if the only thing in the cpp file is a constructor definition for the UInterface class, then yes you should be able to change to GENERATED_BODY and remove the cpp file I’d think.

Sorry guys I edited the original post, it did actually have GENERATED_UINTERFACE_BODY, I just made an error when typing the post.

I remember about GENERATED_BODY() being used to phase things out, which I do use on all my UCLASSes now, I’m still using GENERATED_USTRUCT_BODY for structs though… I guess I should switch those over.

I have no problem with them changing things of course, but it would just be nice to at least have a mention of it in the release notes. I had an issue originally when moving to 4.13 because of pointless override functions being added to gamemode, which also wasn’t mentioned in the release notes.

I think if I had to remove constructor from cpp in order to get GENERATED_BODY() working then you have to add it if you want to use UINTERFACE_BODY

It was just odd, I never had a .cpp class so didn’t have a constructor declared anywhere. Unless I did… and I deleted it during this big rewrite… o.O the plot thickens.

Either way, my current setpu is having NO .cpp file, and using GENERATED_BODY()

Probably you just deleted this, yeah. It’s auto-generated if you create the interface via “New C++ Class” button. I tried this process in 4.13.1 and 4.13.2 - same results. If there were any changes then they were in 4.13.0 :slight_smile:
Yeah, this way is definitely better!
Rewriting all my interfaces at the moment :smiley: