Download

Crash when calling a python function from an editor utility widget blueprint

Hello!

I tried to call a function on a python bridge object I defined from an editor utility widget. However I encounter this casting error when the editor tries to find the right UFunction to execute:

Cast of WidgetBlueprintGeneratedClass /Game/NewEditorUtilityWidgetBlueprint.NewEditorUtilityWidgetBlueprint_C to PythonGeneratedClass failed
(see below, “Additional infos” for more insight and stacktrace on this error)

Can anybody help? Would you have a workaround?

My Setting
Unreal version: 4.22

PythonBridge.h


UCLASS(Blueprintable)
class UPythonBridge : public UObject
{
    GENERATED_BODY()

public:
    /// Get a reference to the Python bridge object, that can then be used to call Python code.
    UFUNCTION(BlueprintCallable, Category = Python)
    static UPythonBridge* GetBridge();

    UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = Python)
    void CheckAllActors() const;
}

PythonBridge.cpp


#include "PythonBridge.h"

UPythonBridge* UPythonBridge::GetBridge()
{
    TArray<UClass*> PythonBridgeClasses;
    GetDerivedClasses(UPythonBridge::StaticClass(), PythonBridgeClasses);
    const int NumClasses = PythonBridgeClasses.Num();
    if (NumClasses > 0)
    {
        return Cast<UPythonBridge>(PythonBridgeClasses[NumClasses - 1]->GetDefaultObject());
    }
    return nullptr;
}

init_unreal.py:


import unreal as ue


@ue.uclass()
class MidnightToolsPythonBridgeImplementation(ue.PythonBridge):
    @ue.ufunction(override=True)
    def check_all_actors(self):
        ue.log_warning("Hello, Python!")


My editor utility widget blueprint:

Relevant stacktrace


     [Inline Frame] UE4Editor-CoreUObject.dll!CastLogError::__l8::<lambda_8a54a48d4a11e0df50e22fb79df3f618>::operator()() Line 10    C++
     UE4Editor-CoreUObject.dll!CastLogError(const wchar_t * FromType, const wchar_t * ToType) Line 10    C++
     UE4Editor-PythonScriptPlugin.dll!CastChecked(UClass * Src) Line 219    C++
     UE4Editor-PythonScriptPlugin.dll!UPythonGeneratedClass::CallPythonFunction(UObject * Context, FFrame & Stack, void * const Z_Param__Result) Line 1807    C++
     UE4Editor-CoreUObject.dll!UFunction::Invoke(UObject * Obj, FFrame & Stack, void * const Z_Param__Result) Line 4643    C++

Additional info

  • Note that my bridge does work when called directly from C++ code (for instance, a toolbar button that once clicked calls [FONT=courier new]PythonBridge::Get()->CheckAllActors()).
  • From what I see in the PyWrapperObject.cpp source of the Python scripting plugin (line 1807), we “Get the correct class from the UFunction so that we can perform static dispatch to the correct type” by trying to cast Stack.Node->GetOwnerClass() to a python generated class, what couldn’t work as the owner of this node is the Widget Utility generated class, that is not a python generated class.

Many thanks in advance! :slight_smile:

Thanks for the report.

I’ve managed to repro this and it seems to be caused by the BP VM invoking the function differently than expected (all Python function calls so far have come via ProcessEvent which ensures the frame is set-up for the event call).

As a workaround for now, you should be able to create a BlueprintCallable wrapper function which calls your BlueprintEvent function (you can probably rename your event to CheckAllActorsImpl and call the new function CheckAllActors without breaking your BP). That will ensure the frame is set-up correctly.

As a side note, you shouldn’t need to do that cast.

It seems even my workaround can cause issues in certain cases (when using non-POD types as outputs).

On the plus side I’ve fixed the calling convention used in our Python thunks for 4.23.