When using CustomStructureParam / CustomThunk, the type you pass in can actually be anything at all. I use an int32 to pass in struct data here. No matter what input type you use, any pin will connect to it (even exec pins).
To enforce some degree of type-safety for the input, you can throw blueprint exceptions during the CustomThunk body if the input doesn’t meet your expectations:
DEFINE_FUNCTION(UMyType::execSomeFunction)
{
Stack.Step(Stack.Object, nullptr);
const FStructProperty* StructProperty = CastField<FStructProperty>(Stack.MostRecentProperty);
const void* StructData = Stack.MostRecentPropertyAddress;
P_FINISH;
// Must have a valid input property
if (!StructProperty || !StructData)
{
FBlueprintExceptionInfo ExceptionInfo(
EBlueprintExceptionType::AccessViolation,
FText::FromString("Input data must be a Struct.")
);
FBlueprintCoreDelegates::ThrowScriptException(P_THIS, Stack, ExceptionInfo);
}
else
{
// etc...
}
}