【发布时间】:2021-04-22 09:44:43
【问题描述】:
我目前正在尝试在我的 Unreal C++ 项目中使用 curl 从公共 git-Repository 下载文件。这是我尝试执行的代码,我从FTP-Example 派生:
// This is in the .h file
struct FFtpFile {
FILE* File;
const char* Filename;
};
void FtpFetch(const std::string URL, const char* Filename) {
CURL* Curl = curl_easy_init();
const FFtpFile FtpFile {
nullptr,
Filename
};
if (!Curl) {
UE_LOG(LogTemp, Warning, TEXT("Error Initiating cURL"));
return;
}
curl_easy_setopt(Curl, CURLOPT_URL, URL.c_str());
curl_easy_setopt(Curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(Curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(Curl, CURLOPT_SSL_VERIFYPEER, false);
// Data Callback
const auto WriteCallback = +[](void* Contents, const size_t Size, const size_t NumMem, FFtpFile* FileStruct) -> size_t {
if (!FileStruct->File) {
fopen_s(&FileStruct->File, FileStruct->Filename, "wb");
if (!FileStruct->File) {
return CURLE_WRITE_ERROR;
}
}
return fwrite(Contents, Size, NumMem, FileStruct->File);
};
curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, DownloadCallback);
curl_easy_setopt(Curl, CURLOPT_WRITEDATA, FtpFile);
const CURLcode Result = curl_easy_perform(Curl);
if (Result != CURLE_OK) {
const FString Message(curl_easy_strerror(Result));
UE_LOG(LogTemp, Warning, TEXT("Error Getting Content of the Model File: %s"), *Message);
return;
}
curl_easy_cleanup(Curl);
// Close the Stream after Cleanup
UE_LOG(LogTemp, Log, TEXT("Successfully Fetched FTP-File. Closing Write Stream"))
if (FtpFile.File) {
fclose(FtpFile.File);
}
}
请注意,这是使用 Unreal Async 函数在单独的线程上执行的:
void AsyncFetchModelFile(const std::string URL) {
std::string Path = ...
TFunction<void()> Task = [Path, URL]() {
FtpFetch(URL, Path.c_str());
};
UE_LOG(LogTemp, Log, TEXT("Fetching FTP on Background Thread"))
Async(EAsyncExecution::Thread, Task, [](){UE_LOG(LogTemp, Warning, TEXT("Finishied FTP on Background Thread!"))});
}
我已经删除了 curl_global 调用,因为文档指出这些调用不是线程安全的。我也尝试在主线程上运行代码,但是那里也发生了同样的错误。
对于错误本身:下载运行几乎完美无缺,但下载的文件(在本例中为 .fbx 文件)总是错过最后约 800 字节,因此不完整。此外,该文件在 Unreal 中一直处于打开状态,因此除非我关闭编辑器,否则我无法删除/移动该文件。
在编写此 Unreal 代码之前,我尝试在纯 C++ 设置中运行相同的代码,并且它完美地运行。但由于某种原因,在 Unreal 中做同样的事情是行不通的。
我也尝试使用私有方法而不是 lambda-Function,但这没有任何区别。
任何帮助将不胜感激 ~冈花
【问题讨论】:
-
听起来好像缓冲区中可能有最后约 800 个字节。为什么是
FtpFileconst?请也显示DownloadCallback函数。 -
顺便说一句,你是在程序开始时调用
curl_global_init,在程序结束时调用curl_global_cleanup吗? -
@TedLyngmo
curl_global_initdocumentation 声明:This function is not thread-safe. You must not call it when any other thread in the program is running所以我从代码中删除了它,因为这段代码在不同的线程上运行。但是放入并不能解决问题。 FtpFile 是 const 因为 Rider 建议我这样做。但这似乎也没有什么不同。我同意这感觉就像最后一批数据没有正确写入文件,但问题是:为什么会这样? -
curl_easy_init文档还声明“如果您还没有调用curl_global_init,curl_easy_init会自动调用。这在多线程情况下可能是致命的,因为curl_global_init不是线程安全的,因为没有相应的清理,可能会导致资源问题。” - 所以,我建议你在程序启动时调用once(然后调用@ 987654337@ 程序退出时一次)。 -
(除非您将其放入 DLL - 不要将其放入
DllMain或在这种情况下的静态初始化程序中)
标签: c++ curl libcurl unreal-engine4