我目前正在尝试将PlayFab C ++ SDK包含到我的应用程序中。该SDK主要用于游戏引擎Cocos2d-x,但基本上可以用于任何C ++应用程序。
它只是普通的REST,因此您将请求发送到它们的服务器并等待响应。这对于使用lambdas是完美的。
他们声明此回调,当请求成功时将调用该回调:
template<typename ResType> using ProcessApiCallback = void(*)(const ResType& result, void* userData);
不幸的是,他们没有使用std :: function,而是一个函数指针。这样一来,便无法使用捕获变量的lambda。
因此,我以为我可以简单地用std :: function回调替换此函数指针回调,如下所示:
template<typename ResType> using ProcessApiCallback = std::function<void(const ResType& result, void* userData)>;
不幸的是,事情并非如此简单,因为它们使用丑陋的reinterpret_casts存储了函数指针,下面是一个示例(删除不必要的部分以使其简短):
void PlayFabClientAPI::LoginWithAndroidDeviceID(
LoginWithAndroidDeviceIDRequest& request,
ProcessApiCallback<LoginResult> callback,
ErrorCallback errorCallback,
void* userData
)
{
// here they assign the callback to the httpRequest
httpRequest->SetResultCallback(reinterpret_cast<void*>(callback));
httpRequest->SetErrorCallback(errorCallback);
httpRequest->SetUserData(userData);
PlayFabSettings::httpRequester->AddRequest(httpRequest, OnLoginWithAndroidDeviceIDResult, userData);
}
稍后,当请求成功时,他们将执行以下操作:
if (request->GetResultCallback() != nullptr)
{
ProcessApiCallback<LoginResult> successCallback = reinterpret_cast<ProcessApiCallback<LoginResult>>(request->GetResultCallback());
successCallback(outResult, request->GetUserData());
}
HttpRequest类具有以下字段:
void* mResultCallback;
问题是我不知道如何在HttpRequest类中存储任意std :: function指针,然后再将其返回。我尝试了很多事情,包括非常丑陋的reinterpret_casting,但没有任何效果。
我愿意对他们的SDK进行任何更改。我也将此报告为不良设计,他们同意,但是他们没有时间对其进行改进,但是如果可以找到好的解决方案,他们将接受拉取请求。
此处的关键信息是userData
指针。它作为请求的一部分提供,并被传递回您的回调函数。这是一个不透明的指针,库不关注它,否则,除了将其转发到您的回调外。
这就是您将在这里使用的。
这是使用C编写的面向服务的通用库的一种非常常见的设计模式。它们的API通常以这种方式构造:它们接受带有额外不透明指针的请求。他们存储该指针,并在请求完成时将其传递回用户提供的回调。
然后,回调将其用于将任何种类的其他元数据与请求相关联。
这是一个C ++库,但是他们选择为库回调实现C风格的设计模式。那真不幸。
但是,无论如何,在您的情况下,您将动态分配std::function
或包含您的的某个类的实例std::function
以及所需的任何其他数据,并将指向动态分配结构的指针传递给请求。
当您的回调被调用时,它只需要reinterpret_cast
指向动态分配类型的不透明指针,复制它的内容delete
(当然,以避免内存泄漏),然后继续将复制的内容用作回调操作的一部分(是否涉及调用std::function
或其他无关紧要的信息)。
由于这是您正在使用的C ++库,而不是C库,因此不幸的是,他们选择实现此C风格的不透明指针传递设计模式。当然,有更好的方法可以用C ++实现,但这是您必须使用的方法,因此您必须处理一个丑陋的事情reintepret_cast
。没有办法避免它。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句