Running a Python script with c++

Or, there’s another snazzy way to do this, which we use in the new Shotgun integration.

Basically you define a base class in C++, with some functions that are marked as “BlueprintImplementableEvent”.


#include "Engine.h"
#include "PythonBridge.generated.h"

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

public:
    UFUNCTION(BlueprintCallable, Category = Python)
    static UPythonBridge* Get();

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


Then you derive a new class from it in Python, in an init_unreal.py script so it gets created at init time, and override those functions with some Python implementation.


import unreal

@unreal.uclass()
class PythonBridgeImplementation(unreal.PythonBridge):

    @unreal.ufunction(override=True)
    def function_implemented_in_python(self):
        unreal.log_warning("Wow! This is the BEST")

You give the base class a Get function that returns its first inherited child.


#include "PythonBridge.h"

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

Then, when you want to call the Python code, say when a menu item is clicked, you can just get the instance and call the function. Behind the scenes, the implementation in Python gets called automatically.


void FTestPythonPlugin::MenuCallback2() {
    UPythonBridge* bridge = UPythonBridge::Get();
    bridge->FunctionImplementedInPython();
}

2 Likes