How to pass an std::string to glShaderSource?

2019-01-13 20:43发布

I have the following code:

glShaderSource(shader, 1, (const char **)data.c_str(), NULL);

But it makes my program crash. How do I convert std::string into const char ** ? I also tried (const char **)& but it said "requires l-value" which I don't understand. It works fine when I use this code:

const char *data = "some code";
glShaderSource(shader, 1, &data, NULL);

But I can't make it work directly from a std::string. I could allocate a new char array for it but that is not nice code.

I also tried with const GLchar but obviously it makes no difference.

8条回答
在下西门庆
2楼-- · 2019-01-13 21:04

Shader.cpp

#include "Shader.hpp"

Shader::Shader(GLenum type)
{
    this->_type = type;
}
Shader::~Shader() {}    

GLuint Shader::get(char* filename)
{
    GLuint shdr = glCreateShader(this->_type);
    FILE* f = 0;
    f = fopen(filename, "r+");
    char* str_tmp = 0;
    char** shdr_text = 0;
    shdr_text = (char**)malloc(sizeof(char**) * 255);
    str_tmp = (char*)malloc(sizeof(char*) * 255);
    int i = 0, ch = 0, n = 0;

    for(i = 0; i < 255; ++i){ *(shdr_text + i) = (char*)malloc(sizeof(char*) * 255); }

    i = 0;
    while((ch = fgetc(f)) != EOF)
    {
        sprintf(str_tmp, "%s%c", str_tmp, ch);
        if(ch == (int)'\n' || ch == (int)'\r')
        {
            sprintf(*(shdr_text + i), "%s", str_tmp);
            sprintf(str_tmp, "");
            ++i;
        }
    }

    free(str_tmp);
    fclose(f);

    glShaderSource(shdr, i, const_cast<const GLchar**>(shdr_text), 0);
    glCompileShader(shdr);

    free(shdr_text);

    return(shdr);
}

Shader.hpp

#ifndef SHADER_HPP
#define SHADER_HPP

#include <stdlib.h>
#include <stdio.h>
#include <GL/glew.h>
#include <GL/gl.h>

class Shader
{
    public:
        Shader(GLenum type);
        virtual ~Shader();

        GLuint get(char* filename);

    private:
        GLenum _type;
};

#endif
查看更多
淡お忘
3楼-- · 2019-01-13 21:06

I only want to point out that the pointer returned by c_str() is only valid as long as you don't do anything that requires reallocation of the internal buffer of std::string. That invalidates the pointer you got.

But since you really require a ** i would do this:

const char* mychararr[1] = {data.c_str()};
glShaderSource(shader, 1, mychararr, NULL);

That should work nicely as long as you don't leave the scope of mychararr.

查看更多
够拽才男人
4楼-- · 2019-01-13 21:07

You can get a reasonable-looking call by using a helper class. Define this class:

struct StringHelper {
  const char *p;
  StringHelper(const std::string& s) : p(s.c_str()) {}
  operator const char**() { return &p; }
};

Then, when you need to call glShaderSource, do it this way:

glShaderSource(shader, 1, StringHelper(data), NULL);
查看更多
叛逆
5楼-- · 2019-01-13 21:11

data.c_str() returns a const char*, so do this:

const char *c_str = data.c_str();
glShaderSource(shader, 1, &c_str, NULL);
查看更多
地球回转人心会变
6楼-- · 2019-01-13 21:14

Try using the .c_str() it give you a char * that you can use as it worked for you b4

#include <string>

void ConversionSample ()
{
 std::string strTest ("This is a string");
 const char* pszConstString = strTest.c_str ();
 }
查看更多
淡お忘
7楼-- · 2019-01-13 21:17

Using string's address and casting it also works in one line:

glShaderSource(vertexShader, 1, (const char* const*)&vertexSource, NULL);

查看更多
登录 后发表回答