私は次のコードを持っています:
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値であり、アドレス演算子を適用できます。したがって、2番目のメソッド(またはダークファルコンのメソッド)が機能するのはそのためです。ただし、返されるポインター値は一時的なものであり、std::string
オブジェクトに対して何らかの操作を行うと、ポインターが無効になる可能性があることに注意してください。 std::string
オブジェクトは、そのデータ構造のメモリを内部的に管理します。したがって、戻りポインタ値をメモリの場所に保存したからといって、後でポインタが無効にならないわけではなく、決定論的に選択することができない場合もあります。
ヘルパークラスを使用すると、見栄えの良い呼び出しを取得できます。このクラスを定義します。
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);
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);
Std :: stringの内部バッファの再割り当てを必要とする処理を何も行わない限り、c_str()
によって返されるポインタが有効であることを指摘したいだけです。それはあなたが得たポインタを無効にします。
しかし、実際には**
私はこれを行います:
const char* mychararr[1] = {data.c_str()};
glShaderSource(shader, 1, mychararr, NULL);
Mychararrのスコープを離れない限り、問題なく動作します。
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
.c_str()を使用してみてください。これにより、char *が得られます。
#include <string>
void ConversionSample ()
{
std::string strTest ("This is a string");
const char* pszConstString = strTest.c_str ();
}