20tab / UnrealEnginePython

Embed Python in Unreal Engine 4
MIT License
2.73k stars 743 forks source link

In UE4.23,the func of "bind_event" will cause crash,how to solve this bug #801

Open BulletHermit opened 4 years ago

BulletHermit commented 4 years ago

When I use bind_event in my python script, it will casues crash. How to solve it or my usage is wrong?

This is my code in python script

def begin_play(self):
    self.uobject.bind_event('OnActorBeginOverlap', self.manage_overlap)
def manage_overlap(self, me, other):
    ue.print_string('overlapping ' + other.get_name())

This is the log of crash.

LoginId:fc0bca1746905f37e5068faf9afa225d EpicAccountId:93eb976f25a3411e89f85a41a23daa15

Unhandled exception

UE4Editor_UnrealEnginePython!TMulticastScriptDelegate::TMulticastScriptDelegate() UE4Editor_UnrealEnginePython!ue_bind_pyevent() [F:\Gayboy\branches\FightGuy_001\Plugins\UnrealEnginePython\Source\UnrealEnginePython\Private\UEPyModule.cpp:3118] UE4Editor_UnrealEnginePython!py_ue_bind_event() [F:\Gayboy\branches\FightGuy_001\Plugins\UnrealEnginePython\Source\UnrealEnginePython\Private\UObject\UEPyObject.cpp:1522] python27 python27 python27 python27 python27 python27 python27 python27 python27 python27 UE4Editor_UnrealEnginePython!APyCharacter::BeginPlay() [F:\Gayboy\branches\FightGuy_001\Plugins\UnrealEnginePython\Source\UnrealEnginePython\Private\PyCharacter.cpp:137] UE4Editor_Engine UE4Editor_Engine UE4Editor_Engine UE4Editor_Engine UE4Editor_Engine UE4Editor_UnrealEd UE4Editor_UnrealEd UE4Editor_UnrealEd UE4Editor_UnrealEd UE4Editor_UnrealEd UE4Editor UE4Editor UE4Editor UE4Editor UE4Editor kernel32 ntdll

avrdan commented 4 years ago

I have the same problem.

However, when I tried debugging, the next instruction after UEPyModule.cpp:3118 jumped to a method from Array.h:

    /**
     * Copies data from one array into this array. Uses the fast path if the
     * data in question does not need a constructor.
     *
     * @param Source The source array to copy
     * @param PrevMax The previous allocated size
     * @param ExtraSlack Additional amount of memory to allocate at
     *                   the end of the buffer. Counted in elements. Zero by
     *                   default.
     */
    template <typename OtherElementType, typename OtherSizeType>
    void CopyToEmpty(const OtherElementType* OtherData, OtherSizeType OtherNum, SizeType PrevMax, SizeType ExtraSlack)
    {
        SizeType NewNum = OtherNum;
        checkf((OtherSizeType)NewNum == OtherNum, TEXT("Invalid number of elements to add to this array type: %llu"), (unsigned long long)NewNum);

        checkSlow(ExtraSlack >= 0);
        ArrayNum = NewNum;
        if (OtherNum || ExtraSlack || PrevMax)
        {
            ResizeForCopy(NewNum + ExtraSlack, PrevMax);
            ConstructItems<ElementType>(GetData(), OtherData, OtherNum);
        }
        else
        {
            ArrayMax = 0;
        }
    }

It failed on: ConstructItems(GetData(), OtherData, OtherNum);

It seems that OtherData has a garbage value.

avrdan commented 4 years ago

Ok, so I fixed this, at least for my use case. Basically, the conversion code to 4.23 is broken in UEPyModule.cpp. In particular, the problems are in lines 3118 and 3133.

I replaced 3118 with:

        // NOTE: only takes the first result from u_property->ArrayDim (can be refactored to do a loop)
        FMulticastScriptDelegate multiscript_delegate = *casted_prop->GetMulticastDelegate(casted_prop->ContainerPtrToValuePtr<void>(u_obj->ue_object));

Then, I replaced 3133 with: casted_prop->SetMulticastDelegate(casted_prop->ContainerPtrToValuePtr<void>(u_obj->ue_object), multiscript_delegate);

Make these changes, rebuild, and it should work.

dfb commented 4 years ago

I'm seeing this crash too. So far this change is working for me (I've changed it only in ue_bind_pyevent and only tested a tiny bit):

if (auto casted_prop = Cast<UMulticastDelegateProperty>(u_property))
{
    FScriptDelegate script_delegate;
    UPythonDelegate* py_delegate = FUnrealEnginePythonHouseKeeper::Get()->NewDelegate(u_obj->ue_object, py_callable, casted_prop->SignatureFunction);
    // fake UFUNCTION for bypassing checks
    script_delegate.BindUFunction(py_delegate, FName("PyFakeCallable"));

#if ENGINE_MINOR_VERSION < 23
    FMulticastScriptDelegate multiscript_delegate = casted_prop->GetPropertyValue_InContainer(u_obj->ue_object);
    multiscript_delegate.Add(script_delegate);
#else
    casted_prop->AddDelegate(script_delegate, u_obj->ue_object);
#endif
}
HaiyiMei commented 2 years ago

Ok, so I fixed this, at least for my use case. Basically, the conversion code to 4.23 is broken in UEPyModule.cpp. In particular, the problems are in lines 3118 and 3133.

I replaced 3118 with:

      // NOTE: only takes the first result from u_property->ArrayDim (can be refactored to do a loop)
      FMulticastScriptDelegate multiscript_delegate = *casted_prop->GetMulticastDelegate(casted_prop->ContainerPtrToValuePtr<void>(u_obj->ue_object));

Then, I replaced 3133 with: casted_prop->SetMulticastDelegate(casted_prop->ContainerPtrToValuePtr<void>(u_obj->ue_object), multiscript_delegate);

Make these changes, rebuild, and it should work.

Solved my issue! Thanks!