【问题标题】:How to properly navigate directory paths in C++如何在 C++ 中正确导航目录路径
【发布时间】:2020-11-29 16:44:52
【问题描述】:

我正在开发 Visual Studio 中的解决方案。它目前有两个项目。

我将用大写字母表示目录或文件夹,文件名将全部小写。我的解决方案结构如下:

  • 解决方案目录
    • 项目库
      • 源文件
      • 着色器
        • 着色器文件
    • 项目应用程序
      • 源文件
    • x64
      • 调试
        • app.exe // 调试构建
      • 发布
        • app.exe // 发布版本

ProjectLib 内,我有一个打开和读取我的着色器文件的功能。这是我的函数的样子:

std::vector<char> VRXShader::readFile(std::string_view shadername) {
    std::string filename = std::string("Shaders/");
    filename.append(shadername);

    std::ifstream file(filename.data(), std::ios::ate | std::ios::binary);

    if (!file.is_open()) {
        throw std::runtime_error("failed to open file!");
    }

    size_t fileSize = static_cast<size_t>(file.tellg());
    std::vector<char> buffer(fileSize);

    file.seekg(0);
    file.read(buffer.data(), fileSize);
    
    file.close();

    return buffer;       
}

这个函数在我的VRXDevices::createPipeline 函数中被调用,这里是相关代码:

void VRXDevices::createPipeline(
    VkDevice device, VkExtent2D swapChainExtent, VkRenderPass renderPass, 
    const std::vector<std::string_view>& shaderNames, 
    VkPipelineLayout& pipelineLayout, VkPipeline& pipeline
) {
    std::vector<std::vector<char>> shaderCodes;
    shaderCodes.resize(shaderNames.size());

    for (auto& name : shaderNames) {
        auto shaderCode = VRXShader::readFile(name.data());
    }

    // .... more code
}

正在创建名称并将其从我的 VRXEngine::initVulkan 函数传递给此函数,可以在此处看到:

void VRXEngine::initVulkan(
    std::string_view app_name, std::string_view engine_name, 
    glm::ivec3 app_version, glm::ivec3 engine_version
) {
    //... code

    std::vector<std::string_view> shaderFilenames{ "vert.spv", "frag.spv" };
    VRXDevices::createPipeline(device_, swapChainExtent_, renderPass_, shaderFilenames, pipelineLayout_, graphicsPipeline_);
    
}

我只使用了着色器文件的名称,例如 vert.spvfrag.spvgeom.spv 等。我不包括此处的路径,因为它们将用作 std::map&lt;string_view, object&gt; 的键.所以我将这些名称的向量从我的::initVulkan 函数传递到::createPipeline()

::createPipeline() 内是调用::readFile() 的地方,传入string_view

现在至于我的问题...在::readFile() 中,我正在创建一个本地string 并尝试使用适当的路径对其进行初始化...然后将string_view 附加到它上面作为着色器的文件名从这两行看...

std::string filename = std::string("Shaders/");
filename.append(shadername);

我正在尝试找出适当的字符串来初始化 filename 与... Shaders/ 将是名称的一部分,但它没有找到文件,我不确定应该使用什么适当的前缀成为...

我在两个项目中的工作目录如下:

  • ProjectApp -> $(SolutionDir)x64/Release 和 $(SolutionDir)x64/Debug
  • ProjectLib -> $(SolutionDir)x64/Release 和 $(SolutionDir)x64/Debug

所以我需要返回 2 个目录然后进入 VRX Engine/Shader...

返回目录的正确字符串值是多少?

我会用"../../VRX Engine/Shaders/" 初始化filename 还是"././",因为文件夹名称中有空格,我应该在VRX Engine 周围加上引号吗?在将shader name 附加到它之前,我需要用什么来初始化filename

【问题讨论】:

  • 我经历了很多试验和错误......但我最终能够用../../VRX Engine/Shaders/打开初始化filename的文件。导致它失败的问题与我的LibProject 或正在构建为静态库的VRX Engine 项目的设置有关。在作为可执行文件构建的Application 中,我有上面描述的适当的working path 目录。我忘记将LibProject 的工作目录更新或修改为相同的...这就是为什么它不起作用并且没有找到或打开文件!

标签: c++ string visual-studio path c++17


【解决方案1】:

我最初使用"../../VRX Engine/Shaders/" 正确初始化我的本地临时string,然后将string_view 附加到它以便能够打开文件。这实际上是正确的,但因为它最初不起作用,所以我认为它是错误的。

返回一个目录的正确字符串值应该是"../",至少在Windows,我不确定LinuxMacAndroid等...

我的问题根本不在于字符串,它与我的项目中的设置有关。在构建为可执行文件的项目中,我将其工作目录分别设置为 $(SolutionDir)x64/Debug$(SolutionDir)x64/Release,这对于我的解决方案结构是正确的。

问题出在我的Engine 项目中,该项目正在构建为静态库。在其工作目录的设置中,我忘记修改 DebugRelease 构建选项...这些仍然设置为 Visual Studio 的默认值,我认为是 (ProjectDir)。一旦我将这些更改为$(SolutionDir)x64/Debug$(SolutionDir)x64/Release 以匹配我的ApplicationProject,我就能够打开并读取文件的内容。

【讨论】:

  • 很高兴您得到了解决方案,感谢您的分享,如果您将它们标记为答案,我将不胜感激,这将对其他社区有益。
  • @BarrnetChou 我必须等待 2 天才能接受我自己的答案!
【解决方案2】:

如何在 C++ 中正确导航目录路径

这取决于您的实现声称符合哪个 C++ 标准。

或者你可以使用哪些额外的库。

C++ 在没有目录的计算机上很有用(例如一些用 C++ 编码并用GCC 编译的操作系统内核,参见OSDEV 的例子)。

详情请关注en.cppreference.com

在使用额外的 open source 库时,许可限制可能很重要。

如果您的实现符合 C++17(以“托管”而非“独立”方式),请使用标准库的 std::filesystem 部分。

如果您的操作系统支持 QtPOCO 框架并且您可以使用它们(例如在 C++11 上),您可以使用适当的 API。所以QDir和Qt相关的类,Poco::Path和POCO相关的类。

也许您只想为WinAPI 编写代码。然后阅读its documentation(我自己从来没有在 Windows 上编写过代码,只是在 POSIX 或 Unix 上——例如 Linux 和 MSDOS ......)。

【讨论】:

  • 感谢您的反馈。我确实知道std::filesystem 是可用的,并且是C++17 标准的一部分,但是,这不是我问题的重点。它指的是正确的字符序列或string 来浏览文件夹或目录。我正在让我的功能正常工作,我正在使用 Visual Studio 在 Windows 机器上构建和测试它。一旦我得到 Vulkan 的框架和样板代码来渲染一个简单的三角形,我就可以回去重构它,使其以跨平台的方式可移植。
  • 另外,我真的不需要使用std::filesystem,所以我必须创建一些测试项目来适应它的界面和内部工作。
猜你喜欢
  • 2020-04-30
  • 2016-12-25
  • 1970-01-01
  • 1970-01-01
  • 2012-01-20
  • 1970-01-01
  • 2011-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多