After much digging and a good amount of debugging, I have the root cause of the issue.
The reasoning behind the byte offset.
While executing the python delegate, the
SelectedItem is interpreted as an
FNameProperty rather than a
FStrProperty. This indirection is where we loose those extra few bytes causing the python cast to fail. Such a cool issue!
This lead me to believe there is a problem with the python delegate generation rather than the conversion tooling. Pretty nifty that the engine doesn’t crash because of this fluke.
The engine builds a dynamic delegate when we use the python script:
That runs, among other things, the delegate metadata scan to pull in information about said delegate (
That call should return us a structure containing the
FStrProperty for the
SelectedItem. Remember, the SelectedItem member in the
ComboBoxString is an
FString. but instead we’re getting a
FNameProperty which breaks the chain.
ComboBoxString is not the only class to define a
FOnSelectionChangedEvent - in fact, the
ComboBoxKey defines a delegate with the same name, but uses an FName parameter instead of the
Here, at last, is our issue.
The python registry for these callbacks uses a flat
TMap<FName, PyTypeObject*> in
PyWrapperTypeRegistry.h. Because these two delegates collide by name, (
OnSelectionChangedEvent__DelegateSignature) we have a cache miss and poof! The error chain is complete and we cannot successfully assign to a
ComboBoxString change delegate via python.
With all of this data compiled, we need to have the python type registry capable of handling multiple delegates with the same name. But it would also be nice to avoid a complex mapping of structures.
The only difference between our delegates, besides their signature, is their owner. Each of them is owned by their respective class (
ComboBoxString). So, with a little extra digging and a small C++ change, I’ve submitted a PR for the engine: