reinterpret_cast into UE interfaces result in access violation error

There is this weird interaction I’ve been encountering lately, Where if I reinterpret cast a parent of class which inherits a UINTERFACE and then call something on it I get an access violation error. For example:

UCLASS()
class AMyActor : public AActor, Public IMyInterface {...}

SomeMethod()
{
    AActor* MyActorInstance = GetMyActorFromSomeWhere();
    IMyInterface* MyInterfaceInstace = reinterpret_cast<IMyInterface*>(MyActorInstance);
    MyInterfaceInstace->DoSomething();
}

This gives an error. While if I use normal Cast instead it works. I have checked the Cast code and it’s basically just a c style cast. How does that work while reinterpret_cast does not?

the UE Cast<T> is not the same as c/c++ cast<T>

the UE Cast<T> is a template function that includes type checking and error handling before the conversion is done.

  • it has a knowledge of UObject and everything that inherits from UObject in your project, and checks the hierarchy first
  • can NOT be used for things that DON"T derive from UObject
  • can be slower at times because it does checks and error handling

while the c/c++ cast<T> (and and other variants including reinterpret_cast) is an operator built to conform to the c/c++ standard, that will forcibly try to do the conversion first then live with the consequences.

  • it only knows whether or not the T is a object type, and tries the conversion “trusting” the programmer
  • is rather fast for integral types, but slows down and can cause issues for complex types.
  • can cause “undefined behavior” (a crash can be the “best” result) if the conversion is not valid

for example in c/c++ you can do

//this is valid, but rarely ever useful unless you are purposely doing "pointer magic"
int* ptr = reinterpret_cast<int*>(somePointer);

if you are using a UObject derived class to a UObject derived class then use UE Cast<T>

and for your example shouldn’t this be dynamic_cast<IMyInterface*> because the interface is typically trying to access thing on the Virtual Function Table?

1 Like

Compiler cannot jump from AActor to IMyInterface, you need to cast to AMyActor inbetween.

Internally, UE is a bit more complex than that. The cast implementation from object to interface uses the reflection system to look up object’s implemented interfaces (stored in the UClass). It accesses the UClass via GetClass() which is polymorphic, so even with your variable of type AActor* it returns the UClass of AMyActor. The UClass contains information about your interface, including its virtual table offset within AMyActor class. Then it can jump to that offset with a c-style cast.

Note the term “Script interface” can be misleading, it designates blueprint-only interfaces.

As long as you stick to C++ interfaces, you should get the same result with the following code :

AActor* Actor = GetMyActorFromSomeWhere();
AMyActor* MyActor = Cast<AMyActor>(Actor);
IMyInterface* Interface = (IMyInterface*)MyActor;
Interface->DoSomething();

Do note that the last cast is useless, as you can call directly MyActor->DoSomething().

And final note, avoid reinterpret_cast in this situation, as it prevents pointer adjustment which may be needed. A c-style cast or static_cast is better suited for upcasting.
See c++ - Does reinterpret_cast guarantee not to change the source pointer's address? - Stack Overflow

2 Likes

Your answer clarified the reason. Thank you ^^b

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.