ROT13
ROT13

Reputation: 375

Reading from a file to a string doesn't work as expected

I'm currently writing my first programm in OpenGl and C/C++. I came across the following problem:

I wrote a method which reads a file (in my case containing the vertex or fragment shader) and returns the content as one string.

std::string loadShader(const char* filepath)
{
    if(filepath){

        std::ifstream ifs(filepath, std::ifstream::in);
        std::ostringstream oss;
        std::string temp;

        while(ifs.good()){

            getline(ifs, temp);
            oss << temp << '\n';
            std::cout << temp << std::endl;

        }
        ifs.close();
        return oss.str();

    }
    else{
       exit(EXIT_FAILURE);
    }
}

I've two files: vertexShader.glsl and fragmentShader.glsl which I want to convert to two seperate strings for the creation of the shaders. The code above is called in the following way:

void createShaders(void){

    GLenum errorCheckValue = glGetError();

    const GLchar* vertexShader = loadShader("vertexShader.glsl").c_str();
    const GLchar* fragmentShader = loadShader("fragmentShader.glsl").c_str();

    vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShaderId, 1, &vertexShader, NULL);
    glCompileShader(vertexShaderId);

    fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL);
    glCompileShader(fragmentShaderId);

    // some other code follows...
}

I debugged the code above and noticed that the vertexShader const char* is empty, while the fragmentShader const char* contains the correct code (the content from the file I just converted to a string).

I don't understand the inconsistency in the method. I can't figure out, how one shader is parsed the right way and the other is empty.

I hope somebody can figure it out. Thank you very much.

Upvotes: 0

Views: 708

Answers (2)

Edward
Edward

Reputation: 7100

The problem is that your unnamed std::string returned from loadShader() only exists within the scope of the expression:

const GLchar* vertexShader = loadShader("vertexShader.glsl").c_str();

Quoting the standard:

Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created.

The fix is simple:

const std::string vertexShaderStr = loadShader("vertexShader.glsl");
const GLchar *vertexShader = vertexShaderStr.c_str();
const std::string fragmentShaderStr = loadShader("fragmentShader.glsl");
const GLchar *fragmentShader = fragmentShaderStr.c_str();

Upvotes: 2

barak manos
barak manos

Reputation: 30136

Change this:

const GLchar* vertexShader = loadShader("vertexShader.glsl").c_str();
const GLchar* fragmentShader = loadShader("fragmentShader.glsl").c_str();

To this:

std::string vertexShaderString = loadShader("vertexShader.glsl");
std::string fragmentShaderString = loadShader("fragmentShader.glsl");
const GLchar* vertexShader = vertexShaderString.c_str();
const GLchar* fragmentShader = fragmentShaderString.c_str();

Upvotes: 1

Related Questions