Announcement

Collapse
No announcement yet.

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

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    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
    Code:
    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
    Code:
    #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:
    Code:
    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:
    Click image for larger version  Name:	Untitled.png Views:	1 Size:	53.6 KB ID:	1624719

    Relevant stacktrace
    Code:
         [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 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!

    #2
    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.
    Last edited by Jamie Dale; 05-28-2019, 05:29 PM.

    Comment


      #3
      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.
      Last edited by Jamie Dale; 06-18-2019, 04:53 PM.

      Comment

      Working...
      X