Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将std::字符串传递给glShaderSource?_C++_String_Opengl_Char - Fatal编程技术网

C++ 如何将std::字符串传递给glShaderSource?

C++ 如何将std::字符串传递给glShaderSource?,c++,string,opengl,char,C++,String,Opengl,Char,我有以下代码: glShaderSource(shader, 1, (const char **)data.c_str(), NULL); 但这让我的程序崩溃了。如何将std::string转换为const char**? 我也试过(const char**)和,但它说“需要l值”,我不明白。当我使用此代码时,它工作正常: const char *data = "some code"; glShaderSource(shader, 1, &data, NULL); 但是我不能直接从s

我有以下代码:

glShaderSource(shader, 1, (const char **)data.c_str(), NULL);
但这让我的程序崩溃了。如何将
std::string
转换为
const char**
? 我也试过
(const char**)和
,但它说“需要l值”,我不明白。当我使用此代码时,它工作正常:

const char *data = "some code";
glShaderSource(shader, 1, &data, NULL);
但是我不能直接从
std::string
使其工作。我可以为它分配一个新的
char
数组,但这不是好代码

我也尝试过使用
const GLchar
,但显然没有什么区别。

data.c_str()
返回一个
const char*
,所以执行以下操作:

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

std::string::c_str()
的返回值是指向保存在
std::string
对象的数据结构中的静态字符串数组的指针值(即地址)。由于返回的只是一个临时的r值(即,它只是一个存储在CPU寄存器中的数字),因此它不是一个l值,因此它没有一个内存地址,您可以实际获取它的地址并将其转换为指向指针的指针。首先必须将返回指针值保存在内存地址中。内存位置是l值,可以应用运算符的地址。这就是为什么第二种方法(或Dark Falcon的方法)有效,尽管请记住返回的指针值是临时的,这意味着如果对
std::string
对象执行任何操作,它可能会使指针无效,因为
std::string
对象在内部管理其数据结构的内存。因此,仅仅因为您已将返回指针值保存在内存位置,并不意味着指针不会在以后某个时间失效,并且在您可能无法确定选择的某个点失效。

尝试使用.c_str(),它会为您提供一个字符*,您可以在为您工作时使用它

#include <string>

void ConversionSample ()
{
 std::string strTest ("This is a string");
 const char* pszConstString = strTest.c_str ();
 }
#包括
void ConversionSample()
{
std::string strTest(“这是一个字符串”);
const char*pszConstString=strTest.c_str();
}

我只想指出,
c_str()
返回的指针只有在不执行任何需要重新分配std::string内部缓冲区的操作时才有效。这会使你得到的指针无效

但由于您确实需要
**
,我会这样做:

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

只要您不离开mychararr的范围,这应该可以很好地工作。

glShaderSource
签名是:

其中
string
“指定指向包含要加载到着色器中的源代码的字符串的指针数组”。您试图传递的是指向以NULL结尾的字符串的指针(即指向
常量char*

不幸的是,我不熟悉
glShaderSource
,但我可以猜到它不应该是指向“某些代码”的指针,而是类似这样的指针:

const char** options =
{
    "option1",
    "option2"
    // and so on
};
从中,您可以阅读一个示例(我特意将其缩短):


通过使用helper类,可以获得外观合理的调用。定义此类:

struct StringHelper {
  const char *p;
  StringHelper(const std::string& s) : p(s.c_str()) {}
  operator const char**() { return &p; }
};
然后,当需要调用
glShaderSource
时,请按以下方式执行:

glShaderSource(shader, 1, StringHelper(data), NULL);
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”
着色器::着色器(格伦类型)
{
此->\u类型=类型;
}
着色器::~Shader(){}
GLuint着色器::获取(字符*文件名)
{
GLuint shdr=glCreateShader(此->\u类型);
文件*f=0;
f=fopen(文件名为“r+”);
char*str_tmp=0;
字符**shdr_text=0;
shdr_text=(char**)malloc(sizeof(char**)*255);
str_tmp=(char*)malloc(sizeof(char*)*255);
int i=0,ch=0,n=0;
对于(i=0;i<255;++i){*(shdr_text+i)=(char*)malloc(sizeof(char*)*255);}
i=0;
而((ch=fgetc(f))!=EOF)
{
sprintf(str_tmp,“%s%c”,str_tmp,ch);
如果(ch==(int)'\n'| ch==(int)'\r')
{
sprintf(*(shdr_text+i),“%s”,str_tmp);
sprintf(str_tmp,“”);
++一,;
}
}
免费(str_tmp);
fclose(f);
glShaderSource(shdr,i,const_cast(shdr_text),0);
政府资讯科技总监(shdr);
免费(shdr_文本);
返回(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
\ifndef着色器\u HPP
#定义着色器\u HPP
#包括
#包括
#包括
#包括
类着色器
{
公众:
着色器(盂型);
虚拟~Shader();
GLuint-get(字符*文件名);
私人:
盂型;
};
#恩迪夫

c_str()return可以分配给l-value@CharlesB:是的,返回值可以分配给l-value,但返回值本身不是l-value,因此您不能将运算符的地址应用于
std::string::c_str()的返回。
。好的,但您的解释有点离题,你不需要这些知识来解决OP问题对不起,我只是觉得这可能会有帮助,并且可能会给情况提供一些背景知识。OP想知道为什么一种方法有效,而另一种方法无效。打印出有效的代码是很好的,但不一定给人工具或理解,以避免将来出现类似情况。其他人已经创建了很好的代码示例,所以我想我会更深入地了解为什么一种方法有效,另一种方法无效,以帮助OP理解根本问题。是否有可能从中删除变量声明,并将其放到我调用函数的一行?@Rookie-Declare,但不要初始化,
c_str
某处:
const char*c_str。然后,在使用时,尝试以下操作:
glShaderSource(shader,1,&(c_str=data.c_str()),NULL)我认为你不能使用一行程序
glShaderSource
需要一个字符串数组(
const char**
=数组
const char*
),而您的
std::string
只提供一个字符串。您必须添加一级间接寻址,以便
glShaderSource
获取一个指针,它可以反引用以检索字符串。@Rob:注意
const char*c_str#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);
}
#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