I am having trouble with the ProcessEvent function. I have a UFunction which has a void return value and only one parameter, a (subclassed) player controller pointer.
The piece of code looks like this (it is inside the subclassed player controller class):
Object->ProcessEvent(Function, this);
Executing this throws and exception which looks like this:
Access violation reading location 0xFFFFFFFFFFFFFFF.
Yep the object and function exist, the exeption is thrown in the UFunction that is called when accessing the parameter I pass in, which in this case is a player controller (this). I experimented with this a while ago and found an ugly workaround, which involved adding a player controller pointer UPoperty to the player controller, assigning the current player controller (this) to it and then passing the controller with the ContainerPtrToValuePtr function to it.
It looked like this:
The above code actually worked as opposed to simply giving the ProcessEvent function a “this” pointer.
I don’t need this function anymore because I ended up with a different system, still I would be curious to know what I did wrong here.
The object you pass to ProcessEvent is used as a container OF your arguments, not as the arguments themselves.
You need to create an object that holds the parameters you are passing and send that pointer to ProcessEvent.
Can you give me an example of what that would look like? That defenitely makes sense because the parameter could also be a return value or multiple input parameters, though in the past it worked for functions which only have one parameter and no return value to just pass in a pointer to the value (as in the workaround example, or simpler just something like ProcessEvent(Function, &bVisible)).
When you’re passing a single parameter (other than “this”) you can pass it directly as a pointer (e.g. &bVisible) and it will work.
If you need to pass “this” (because c++ won’t let you pass “&this”), or if you are passing multiple parameters, and/or if you are accessing a return value you can do something like this:
//define a container
struct FDynamicArgs
{
float Arg01 = 100.0f;
AActor* Arg02 = NULL;
float Return = 0.0f;
};
//create the container
FDynamicArgs Args = FDynamicArgs();
//You must assign "this" outside the generic struct,
//or within the struct's context "this" will refer to the
//struct itself.
//Alternatively, you can create a construction method
//for the struct and pass "this" as an argument there
Args.Arg02 = this;
//then pass the container by reference, along with the function pointer
TargetObject->ProcessEvent(TargetMethod, &Args);
You can also create a predefined struct (or other container object) elsewhere rather than dynamically defining it here.
Arguments are parsed by type in the order assigned.
Any trailing parameters of the appropriate type will be assigned the return value (if any).
Bear in mind that your container and any contained values will only exist for the life of the method they are created within; so if you need the return value outside this method you’ll need to preserve it somehow (assign to a referenced argument, return the value, etc.).