Subscribing to a dynamic multicast delegate via a wrapper function

Hi folks,

I’m trying to subscribe to a dynamic multicast delegate using a wrapper function that does some management of my event system before adding the delegate subscription.

I’m using a dynamic multicast because I want it to be assignable both in C++ and in blueprints. It has the signature:

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FGameplayEventSignature, UObject*, Sender, UGameplayEventArgs*, EventArgs);

I’m having trouble figuring out how to format the function so that it takes the correct params to call AddDynamic/RemoveDynamic though.

static void AddListener(T* Listener, TYPE ListenerFunction)
{
    // Do stuff here

    MyDelegate.AddDynamic(Listener, ListenerFunction);
}

I have a working wrapper function using a non-dynamic multicast delegate that takes the object pointer and function name and subscribes via AddUFunction(ObjectPtr*, FunctionName), but this requires me to keep a FDelegateHandle to successfully remove the function later. Also I can’t make it BlueprintAssignable.

Is it possible to have a wrapper function that will pass the correct type of data to use a dynamic multicast delegate’s AddDynamic/RemoveDynamic macros?

Dynamic delegates are bound by name, and AddDynamic macro uses preprocessor string processing on the passed function pointer to retrieve its name, so the only way you can wrap it is with another macro :

#define AddListener(Object, Function) \
    _Internal_AddListener(Object, Function); \
    MyDelegate.AddDynamic(Object, Function);

template<class UserClass>
static void _Internal_AddListener(UserClass* Object, typename FDelegate::template TMethodPtrResolver<UserClass>::FMethodPtr Function)
{
    // Do stuff here
}

Alternatively, you can call the __Internal_AddDynamic method directly, but it requires the function name, so it’s a bit redundant, which is why a macro exists to make it simpler.

static void AddListener(T* Listener, TYPE ListenerFunction, FName FuncName)
{
    // Do stuff here

    MyDelegate.__Internal_AddDynamic(Listener, ListenerFunction, FuncName);
}

//Usage: AddListener(Object, &UMyObject::SomeFunction, "SomeFunction");