Hey Rama,
As far as I am aware, and as you concluded, there is no direct way to place a UFUNCTION on a USTRUCT.
I believe they made this decision because they treat structs inside of a blueprint as simple data containers (kind of like POD, but a bit different). They are meant to be passed and stored purely by value (for example, you cannot create a USTRUCT* UPROPERTY). Because of this, they are not garbage collected.
This allows USTRUCT’s to be very efficient and cheap to work with, as they are not forced to inherit UObject like a UCLASS is.
Unfortunately, it also means they can’t contain UFUNCTION’s, because they are not compatible with delegates.
Think of it this way. Any UFUNCTION can be stored within a delegate. The delegate requires a pointer to both the function definition and the target object in order to work. The function definition does not change location in memory, and can therefore be statically referenced (meaning it does not need any garbage collection or ‘safe pointer’ support). The target object, however, is much less reliable. It could be deleted at any time, leading to memory corruption if the delegate was executed and not properly checked. Being a USTRUCT, the target object would not work with ‘safe pointer’ classes, and could not be garbage collected.
To bring this back to your specific question, K2Nodes (such as K2_CallFunction) use a system similar to delegates (thought to be fair, a bit different). They rely on UObjects, both to store ‘target objects’ and to trawl their UClass for the function definition. This will not work with USTRUCT’s.
Now I could be wrong. They could potentially do some magic behind the scenes that could make it work (such as bypassing the need for ‘delegates’ when linking up a blueprint graph). They could hard-link the methods in their pre-processing build tool. I don’t have access to their engine code after all, so I am just making an educated guess. I would very much doubt it, however, and their exposed classes seem to support my deduction. The additional complexity and loss of flexibility in other areas would do more harm than good. This may well change in the future, but for now I think we have to rely on blueprint function libraries.