Announcement

Collapse
No announcement yet.

FString as Delegate Payload Data

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    FString as Delegate Payload Data

    Hi everyone!

    Summary:
    I am unable to pass FString as payload data to DelegateXY().BindUObject().

    Detailed Description:
    I am implementing an OnlineSubsystem and need to pass the Access token (FString) to a HTTP request complete delegate as payload data: *

    Code:
    /* Pseudo: */
    FString AccountCredentials.Token;
    in32 LocalUserNum;
    
    /* The code in question: */
    TSharedRef<IHttpRequest> r = FHttpModule::Get().CreateRequest();
    r->OnProcessRequestComplete().BindUObject(this, &FOnlineIdentityXYZ::OnGetUserDataResponse, /* payload data: */ LocalUserNum, AccountCredentials.Token);
    // ...
    But then I get

    Code:
    12>D:\[...]\Source\Private\OnlineIdentityXYZ.cpp(95): error C2664: 'void TBaseDelegate<TTypeWrapper<void>,FHttpRequestPtr,FHttpResponsePtr,bool>::BindUObject<FOnlineIdentityXYZ,int32,FString>(UserClass *,void (__cdecl FOnlineIdentityXYZ::* )(FHttpRequestPtr,FHttpResponsePtr,bool,int32,FString) const,int32,FString)': cannot convert argument 2 from 'void (__cdecl FOnlineIdentityXYZ::* )(FHttpRequestPtr,FHttpResponsePtr,bool,int32,const FString &)' to 'void (__cdecl FOnlineIdentityXYZ::* )(FHttpRequestPtr,FHttpResponsePtr,bool,int32,FString)'
    Since my method accepts const String&, but C++ deduces String as the template paramter, which is acceptible. So I went ahead and explicitly specified the types for the payload data:

    Code:
    r->OnProcessRequestComplete().BindUObject<FOnlineIdentityXYZ, int32, const FString&>(this, &FOnlineIdentityXYZ::OnGetUserDataResponse, LocalUserNum, AccountCredentials.Token);
    Which results in the following different compile error:

    Code:
    D:\[...]\UnrealEngine\Engine\Source\Runtime\Core\Public\Delegates/DelegateSignatureImpl.inl(512): error C2665: 'TBaseDelegate<TTypeWrapper<void>,FHttpRequestPtr,FHttpResponsePtr,bool>::CreateUObject': none of the 2 overloads could convert all the argument types
      D:\[...]\UnrealEngine\Engine\Source\Runtime\Core\Public\Delegates/DelegateSignatureImpl.inl(286): note: could be 'TBaseDelegate<void,FHttpRequestPtr,FHttpResponsePtr,bool> TBaseDelegate<TTypeWrapper<void>,FHttpRequestPtr,FHttpResponsePtr,bool>::CreateUObject<UserClass,int32,FString>(UserClass *,void (__cdecl FOnlineIdentityXYZ::* )(FHttpRequestPtr,FHttpResponsePtr,bool,int32,FString) const,int32,FString)'
              with
              [
                  UserClass=FOnlineIdentityXYZ
              ]
      D:\[...]\UnrealEngine\Engine\Source\Runtime\Core\Public\Delegates/DelegateSignatureImpl.inl(277): note: or       'TBaseDelegate<void,FHttpRequestPtr,FHttpResponsePtr,bool> TBaseDelegate<TTypeWrapper<void>,FHttpRequestPtr,FHttpResponsePtr,bool>::CreateUObject<UserClass,int32,FString>(UserClass *,void (__cdecl FOnlineIdentityXYZ::* )(FHttpRequestPtr,FHttpResponsePtr,bool,int32,FString),int32,FString)'
              with
              [
                  UserClass=FOnlineIdentityXYZ
              ]
      D:\[...]\UnrealEngine\Engine\Source\Runtime\Core\Public\Delegates/DelegateSignatureImpl.inl(512): note: while trying to match the argument list '(FOnlineIdentityXYZ *, void (__cdecl FOnlineIdentityXYZ::* )(FHttpRequestPtr,FHttpResponsePtr,bool,int32,const FString &), int32, const FString)'
      D:\[...]\UnrealEngine\Engine\Plugins\Online\OnlineSubsystemXYZ\Source\Private\OnlineIdentityXYZ.cpp(95): note: see reference to function template instantiation 'void TBaseDelegate<TTypeWrapper<void>,FHttpRequestPtr,FHttpResponsePtr,bool>::BindUObject<FOnlineIdentityXYZ,int32,const FString&>(UserClass *,void (__cdecl FOnlineIdentityXYZ::* )(FHttpRequestPtr,FHttpResponsePtr,bool,int32,const FString &),int32,const FString &)' being compiled
              with
              [
                  UserClass=FOnlineIdentityXYZ
              ]
      D:\[...]\UnrealEngine\Engine\Plugins\Online\OnlineSubsystemXYZ\Source\Private\OnlineIdentityXYZ.cpp(95): note: see reference to function template instantiation 'void TBaseDelegate<TTypeWrapper<void>,FHttpRequestPtr,FHttpResponsePtr,bool>::BindUObject<FOnlineIdentityXYZ,int32,const FString&>(UserClass *,void (__cdecl FOnlineIdentityXYZ::* )(FHttpRequestPtr,FHttpResponsePtr,bool,int32,const FString &),int32,const FString &)' being compiled
              with
              [
                  UserClass=FOnlineIdentityXYZ
              ]
    Passing a reference doesn't seem to be enough anyway, since the data will get deallocated before the delegate is called, so I am guessing my approach must be entirely wrong. (I hoped the BindUObject would magically do all the necessary copying etc.)

    I also tried FString directly (by-"value"), which would probably result in 2 copies instead of the one required (the performance doesn't really matter here, but ugh). Then the compiler complains about raw pointers not being allowed in delegates.

    * The access token needs to be passed to the FUserOnlineAccountXYZ constructor which is called in the bound delegate. I understand that a alternative is to create the FUserOnlineAccountXYZ, pass a SharedPtr/SharedRef to the delegate and use setters. I want the object to be immutable, though. Apart from that I am sure that this use case will appear for me in the future again, one way or another.

    Answers that would help:
    If you can answer one of these questions, I would be able to find a clean solution:
    • How do I create a SharedRef from an FString? (MakeShareable(myStr))? And would that be the intended/recommended way of doing this?
    • Do you know code in the engine, where this is done?
    • Do you know a open source plugin, where this has been done?
    • Do you know some line of documentation that states this is not possible by design?


    I can imagine a ton of ugly workarounds (like passing a pointer to a heap allocated char array as long for example, creating a member array of strings and passing the index etc.). What I'm looking for is either a clean solution or documentation that explicitly states this is impossible.

    Thank you very much in advance!
    Last edited by Squareys; 04-17-2017, 02:03 AM. Reason: Fix bogus wording of workaround description

    #2
    The solution was that FOnlineIdentityXYZ is not a UObject and I can therefore not use BindUObject, but must use BindRaw instead. In addition I am now using
    Code:
    TSharedPtr<FString> shareableToken = MakeShareable<FString>(new FString(AccountCredentials.Token));
    ... and pass that to BindRaw to ensure the FString isn't dealocated when it goes out of scope.
    May this help someone else out there!

    Comment

    Working...
    X