web-dev-qa-db-ja.com

std :: stringをglShaderSourceに渡す方法は?

私は次のコードを持っています:

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

しかし、それは私のプログラムをクラッシュさせます。 std::stringconst char **に変換するにはどうすればよいですか?私も(const char **)&を試しましたが、「L値が必要」とわかりません。このコードを使用するとうまくいきます:

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

ただし、std::stringから直接機能させることはできません。新しいchar配列を割り当てることもできますが、それはいいコードではありません。

私はconst GLcharも試しましたが、明らかに違いはありません。

28
Rookie

data.c_str()const char*を返すので、次のようにします。

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

std::string::c_str()の戻り値は、std::stringオブジェクトのデータ構造内に保持されている静的文字列配列へのポインタ値(つまり、アドレス)です。戻り値は一時的なr値(つまり、CPUレジスタに格納された単なる数値)であるため、l値ではなく、したがってメモリアドレスがありません。実際にアドレスを取得して、ポインターツーポインターにキャストします。最初に、戻りポインタ値をメモリアドレスに保存する必要があります。メモリ位置はl値であり、アドレス演算子を適用できます。したがって、2番目のメソッド(またはダークファルコンのメソッド)が機能するのはそのためです。ただし、返されるポインター値は一時的なものであり、std::stringオブジェクトに対して何らかの操作を行うと、ポインターが無効になる可能性があることに注意してください。 std::stringオブジェクトは、そのデータ構造のメモリを内部的に管理します。したがって、戻りポインタ値をメモリの場所に保存したからといって、後でポインタが無効にならないわけではなく、決定論的に選択することができない場合もあります。

14
Jason

ヘルパークラスを使用すると、見栄えの良い呼び出しを取得できます。このクラスを定義します。

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);
11
Robᵩ

glShaderSource署名は glShaderSource doc によると:

void glShaderSource(
    GLuint shader,
    GLsizei count,
    const GLchar** string,
    const GLint* length);

ここで、string "シェーダーにロードされるソースコードを含む文字列へのポインターの配列を指定します。"渡そうとしているのは、NULLで終了する文字列へのポインター(つまり、const char*へのポインター)です。

残念ながら、私はglShaderSourceに精通していませんが、「一部のコード」へのポインタではなく、次のようなものであるとは思われません。

const char** options =
{
    "option1",
    "option2"
    // and so on
};

opengl-redbook から、例を読むことができます(目的に合わせて短縮しました)。

const GLchar* shaderSrc[] = {
    "void main()",
    "{",
    "    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;",
    "}"
};
shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(shader, NumberOfLines(shaderSrc), shaderSrc, NULL);
7
mister why

Std :: stringの内部バッファの再割り当てを必要とする処理を何も行わない限り、c_str()によって返されるポインタが有効であることを指摘したいだけです。それはあなたが得たポインタを無効にします。

しかし、実際には**私はこれを行います:

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

Mychararrのスコープを離れない限り、問題なく動作します。

2
RedX

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
1
Imagine Breaker

.c_str()を使用してみてください。これにより、char *が得られます。

#include <string>

void ConversionSample ()
{
 std::string strTest ("This is a string");
 const char* pszConstString = strTest.c_str ();
 }
0
Luis Tellez