Search code examples
c++unreal-engine4

How to add a UFunction to an interface's delegate with parameters in UE4 C++?


I am looking use web sockets in Unreal. I am following the tutorial found here: Web Socket Tutorial

Most notably I am trying to bind to the events before connection. In the example, they use .AddLambda however, I would like to try to use .AddUFunction. It seems the function takes in the Object, the function name, and VarTypes ...types. I can't seem to figure out what the last parameter is for the delegates that use parameters. (At least I believe that is the problem anyway) The functions themselves have the correct signature and matches the delegates I want to bind to.

Here is what I have so far:

void AWebSocketController::CreateWebSocket(FString ServerUrl, FString ServerProtocol)
{
  Socket = FWebSocketsModule::Get().CreateWebSocket(ServerUrl, ServerProtocol);

  // We bind to the events
  Socket->OnConnected().AddUFunction(this, FName("OnSocketConnection"));

  Socket->OnConnectionError().AddUFunction(this, FName("OnSocketConnectionError"));

  Socket->OnClosed().AddUFunction(this, FName("OnSocketClosed"));

  Socket->OnMessage().AddUFunction(this, FName("OnSocketReceiveMessage"));

  Socket->OnMessageSent().AddUFunction(this, FName("OnSocketSentMessage"));

  // And we finally connect to the server. 
  Socket->Connect();

}

It gives me the following error messages:

error LNK2005: "public: void __cdecl AWebSocketController::OnSocketClosed(int,class FString const &,bool)" (?OnSocketClosed@AWebSocketController@@QEAAXHAEBVFString@@_N@Z) already defined in WebSocketController.cpp.obj
error LNK2005: "public: void __cdecl AWebSocketController::OnSocketConnection(void)" (?OnSocketConnection@AWebSocketController@@QEAAXXZ) already defined in WebSocketController.cpp.obj
error LNK2005: "public: void __cdecl AWebSocketController::OnSocketConnectionError(class FString const &)" (?OnSocketConnectionError@AWebSocketController@@QEAAXAEBVFString@@@Z) already defined in WebSocketController.cpp.obj
error LNK2005: "public: void __cdecl AWebSocketController::OnSocketReceiveMessage(class FString const &)" (?OnSocketReceiveMessage@AWebSocketController@@QEAAXAEBVFString@@@Z) already defined in WebSocketController.cpp.obj
error LNK2005: "public: void __cdecl AWebSocketController::OnSocketSentMessage(class FString const &)" (?OnSocketSentMessage@AWebSocketController@@QEAAXAEBVFString@@@Z) already defined in WebSocketController.cpp.obj

The function definitions:

void AWebSocketController::OnSocketConnection()
{
}

void AWebSocketController::OnSocketConnectionError(const FString& ErrorMessage)
{
}

void AWebSocketController::OnSocketClosed(int32 StatusCode, const FString& Reason, bool WasClean)
{
}

void AWebSocketController::OnSocketReceiveMessage(const FString& Message)
{
}

void AWebSocketController::OnSocketSentMessage(const FString& Message)
{
}

I have never come across this .AddUFunction before and I can't seem to find any examples of how to use it. If anyone can help me out or point me in the right direction, it would be appreciated.


Solution

  • Works for me!

    SandboxGameInstance.cpp

    #include "SandboxGameInstance.h"
    
    #include "WebSocketsModule.h"
    #include "IWebSocket.h"       // Socket definition
    void USandboxGameInstance::Init()
    {
        Super::Init();
        FWebSocketsModule& Module = FModuleManager::LoadModuleChecked<FWebSocketsModule>(TEXT("WebSockets"));
    
        const FString ServerURL = TEXT("ws://127.0.0.1:3000/"); // Your server URL. You can use ws, wss or wss+insecure.
        const FString ServerProtocol = TEXT("ws");              // The WebServer protocol you want to use.
    
        TSharedPtr<IWebSocket> Socket = FWebSocketsModule::Get().CreateWebSocket(ServerURL, ServerProtocol);
    
        // We bind to the events
        Socket->OnConnected().AddUFunction(this, FName("OnSocketConnection"));
    
        Socket->OnConnectionError().AddUFunction(this, FName("OnSocketConnectionError"));
    
        Socket->OnClosed().AddUFunction(this, FName("OnSocketClosed"));
    
        Socket->OnMessage().AddUFunction(this, FName("OnSocketReceiveMessage"));
    
        Socket->OnMessageSent().AddUFunction(this, FName("OnSocketSentMessage"));
    
        // And we finally connect to the server. 
        Socket->Connect();
    }
    
    void USandboxGameInstance::OnSocketConnection()
    {
        UE_LOG(LogTemp, Warning, TEXT("CONNECTED"));
    }
    
    void USandboxGameInstance::OnSocketConnectionError(const FString& ErrorMessage)
    {
        UE_LOG(LogTemp, Warning, TEXT("ERROR"));
    }
    
    void USandboxGameInstance::OnSocketClosed(int32 StatusCode, const FString& Reason, bool WasClean)
    {
        UE_LOG(LogTemp, Warning, TEXT("CLOSED"));
    }
    
    void USandboxGameInstance::OnSocketReceiveMessage(const FString& Message)
    {
        UE_LOG(LogTemp, Warning, TEXT("RECEIVED"));
    }
    
    void USandboxGameInstance::OnSocketSentMessage(const FString& Message)
    {
        UE_LOG(LogTemp, Warning, TEXT("SENT"));
    }
    

    SandboxGameInstance.h

    #pragma once
    
    #include "CoreMinimal.h"
    #include "Engine/GameInstance.h"
    #include "SandboxGameInstance.generated.h"
    
    UCLASS()
    class SANDBOX_API USandboxGameInstance : public UGameInstance
    {
        GENERATED_BODY()
    public:
        virtual void Init() override;
    
        UFUNCTION()
        void OnSocketConnection();
    
        UFUNCTION()
        void OnSocketConnectionError(const FString& ErrorMessage);
    
        UFUNCTION()
        void OnSocketClosed(int32 StatusCode, const FString& Reason, bool WasClean);
    
        UFUNCTION()
        void OnSocketReceiveMessage(const FString& Message);
    
        UFUNCTION()
        void OnSocketSentMessage(const FString& Message);
    };