试图使用cmake打开ifstream的文件的问题

Problem trying to open a file with ifstream using CMake

本文关键字:ifstream 文件 问题 打开 cmake      更新时间:2023-10-16

/*定义班级着色器。*/

我正在开发带有OpenGL和CMAKE的C 的应用程序。我目录的结构是:

  • tanx
    • cmakelists.txt
    • ext(包含glfw and Glad)
    • SRC
      • tanx.cpp
      • tanx.h
      • 数学(包含几种数学方法;与我的问题不太相关)
      • 着色器
        • Shader.h
        • vertex.glsl
        • fragment.glsl
        • cmakelists.txt

Shader.h IST主要应该从文件中读取顶点和片段着色源,将其编译并将其链接到着色器程序。看起来这样:

#ifndef _SHADER_H
#define _SHADER_H
#include <string>
#include <exception>
#include <fstream>
#include <glad.h>

class shader_exception :std::exception {
private:
    const char* text;
public:
    shader_exception(const char* text)
        : text(text) {}
    virtual const char* what() const {
        return text;
    }
};
class Shader {
private:
    std::string* vertex_source = new std::string();
    std::string* fragment_source = new std::string();
    unsigned int vao, vbo, vertex_shader, fragment_shader, program;
public:
    Shader(const char* vertex_source_path, const char* fragment_source_path) {
        std::ifstream file_reader;
        file_reader.open(vertex_source_path);
        std::string line;
        if (file_reader.is_open()) {
            while (getline(file_reader, line)) {
                vertex_source->append(line + "n");
            }
            file_reader.close();
        }
        else 
            throw shader_exception("Could not open vertex shader source file");
        file_reader.open(fragment_source_path);  // this is where I get an unhandled exception dialog box
        if (file_reader.is_open()) {
            while (getline(file_reader, line)) {
                fragment_source->append(line + "n");
            }
            file_reader.close();
        }
        else
            throw shader_exception("Could not open fragment shader file");
        const char** vertex_source_c = (const char**)malloc(vertex_source->size());
        *vertex_source_c = vertex_source->c_str();
        const char** fragment_source_c = (const char**)malloc(fragment_source->size());
        *fragment_source_c = fragment_source->c_str();
        vertex_shader = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertex_shader, 1, vertex_source_c, NULL);
        glCompileShader(vertex_shader);
        int success;
        glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
        char infoLog[512];
        if (!success) {
            glGetShaderInfoLog(vertex_shader, 512, NULL, infoLog);
            throw shader_exception(infoLog);
        }
        glShaderSource(fragment_shader, 1, fragment_source_c, NULL);
        glCompileShader(fragment_shader);
        glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
        if (!success) {
            glGetShaderInfoLog(fragment_shader, 512, NULL, infoLog);
            throw shader_exception(infoLog);
        }
        program = glCreateProgram();
        glAttachShader(program, vertex_shader);
        glAttachShader(program, fragment_shader);
        glLinkProgram(program);
        glGetProgramiv(program, GL_LINK_STATUS, &success);
        if (!success) {
            glGetProgramInfoLog(program, 512, NULL, infoLog);
            throw shader_exception(infoLog);
        }
        glDeleteShader(vertex_shader);
        glDeleteShader(fragment_shader);
    }
    Shader() = delete;
    void use() 
    {
        glUseProgram(program);
    }
    ~Shader() {
        glDeleteProgram(program);
    }
};
#endif

在tanx.cpp中,我尝试创建这样的着色器对象:

Shader shader("vertex.glsl", "fragment.glsl");

您可以看到,我想使用的着色器源文件是位于" Shader" - 文件夹中的Vertex.glsl和Fragment.glsl。为了使它们可用于ifstream,cmakelists.txt文件看起来像这样(这是此处提到的选择,以使该文件适用于该程序):

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/vertex.glsl ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fragment.glsl ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)

顶级cmakelists.txt文件也包含

add_subdirectory("TanX/src/Shader")

以便执行着色器中的cmakelists.txt文件。

问题是,当我尝试在Visual Studio中运行代码时,在第45行(尝试打开Fragment.glsl)的Shader.h文件中得到一个未经处理的例外。这是一个Shader_Exception,因此显然打开Vertex.glsl失败。tanx.exe中的0x00007fff43e4a388 in tanx.exe:Microsoft C 例外:存储器位置0x0000000028896ff608。现在我有两个问题

1)我该怎么做才能让ifstream打开vertex.glsl(然后在那之后fragment.glsl)?
2)为什么我什至会遇到一个未经治疗的异常错误,一旦抛出了异常,着色器对象的构建也不应失败,而导致该程序甚至没有达到第45行?

马上,这个...

Shader* shader;
try {
    *shader = Shader("vertex.glsl", "fragment.glsl");
}

...是未定义的行为,因为您正在取消一个非初始化的指针(即,您没有为Shader对象分配任何存储空间)。这可能不是唯一的问题,但它是一个关键问题,必须在您进一步调试之前必须修复(因为程序之后的行为是不可预测的)。

您可能打算写:

shader = new Shader(...);

(实际上,您应该将std::unique_ptr用于此而不是裸露的指针,但这是从原始问题的范围中转向的。除其他好处外,它使这种错误易于发现和避免。)bk_hr>

至于其他问题,您是否检查了该程序是否在.glsl文件所在的目录中运行?传递给文件流的相对路径相对于程序的当前工作目录解释了,而不是相对于原始源文件的位置。

根据我的计数,第45行是...

}

...所以似乎错过了。发布实际的程序输出和异常信息(或对话框内容)以及显示调试器所指示的行将很有帮助。

问题是我将文件放在哪里。我将它们放入着色器文件夹的bin文件夹中,但是由于它在标题中实现,正确的位置是顶级文件夹的bin文件夹。