C ++, OpenGL: странная проблема с c-строками - PullRequest
1 голос
/ 09 декабря 2010

У меня проблема с C ++, которую я просто не могу понять.

У меня есть 2 слегка отличающиеся функции. Они оба должны делать то же самое. Но только один работает правильно.

Метод 1: входные данные метода: 'const string samplerName = "test"'


void setUniformSampler(Gluint program, const string samplerName, GLuint sampler) {
    GLint uniformLocation = glGetUniformLocation(program, samplerName.c_str()); // returns -1

    if(uniformLocation >= 0) {
        glUniform1i(uniformLocation, sampler);
    } else {
        throw exception(...);
    }
}

Метод 2:


void setUniformSampler(Gluint program, GLuint sampler) {
    GLint uniformLocation = glGetUniformLocation(program, "test"); // returns 0

    if(uniformLocation >= 0) {
        glUniform1i(uniformLocation, sampler);
    } else {
        throw exception(...);
    }
}

Как видите, glGetUniformLocation возвращает 2 разных значения. Правильным возвращаемым значением будет «0», а не «-1». Поэтому мне интересно, в чем именно разница между двумя вызовами?

quote: «c_str () генерирует завершающуюся нулем последовательность символов (c-string) с тем же содержимым, что и строковый объект, и возвращает его в качестве указателя на массив символов». И это именно то, что нужно методу glGetUniformLocation (...) в качестве второго параметра. Так почему же только метод 2 выше? Это проблема компилятора?

Я работаю с MS Visual Studio 2008 на Win7.

Я искал эту ошибку почти 2 дня. Я действительно хочу уточнить это. Это сводило меня с ума ...

Спасибо Walter

EDIT:

Это тоже не работает.


void setUniformSampler(Gluint program, const string samplerName, GLuint sampler) {
    const GLchar* name = samplerName.c_str();

    GLint uniformLocation = glGetUniformLocation(program, name); // still returns -1

    if(uniformLocation >= 0) {
        glUniform1i(uniformLocation, sampler);
    } else {
        throw exception(...);
    }
}

Ответы [ 3 ]

0 голосов
/ 09 декабря 2010

проверьте реализацию и тип параметра в glGetUniformLocation(parameter), «test» - это константный литерал, жизнь и местоположение которого никогда не меняются в жизни вашего исполняемого файла, в то время как c_str () динамически вычисляется из строкового объекта, он умирает, когда строковый объект умирает.

Другими словами, вам нужно проверить сторону glGetUniformLocation(), чтобы найти причину, которая, как мне кажется, связана с некоторыми строковыми функциями CRT.

0 голосов
/ 09 декабря 2010

Возможно, вы стали жертвой сочетания широких символов и тонких (то есть 8-битных) строк символов. Если и ваш источник шейдера, и унифицированное имя определены как статические строки, тогда они согласятся на строковое представление. string :: c_str может изменить это, поскольку c_str всегда будет возвращать строку char, то есть она не знает wchar.

Технически это должно иметь значение, так как компилятор без ошибок использует однозначное внутреннее представление. Но может быть ошибка в том, что разница между широкими и тонкими символами интерпретируется как разные идентификаторы.

Что произойдет, если вы передадите источник шейдера тоже через string :: c_str? Также проверьте представление hexedit отладчика на строковой переменной. Если это выглядит так:

00000000  74 65 73 74 0a                                    |test.|

Вы получили 8-битную строку символов. Если это выглядит так:

00000000  74 00 65 00 73 00 74 00  0a 00                    |t.e.s.t...|

тогда вы получили широкую строку. А затем сравните это с переменной, в которую входит шейдер.

0 голосов
/ 09 декабря 2010

Ваш параметр является константным, и вы не можете вызвать неконстантную функцию для константного объекта. Может в этом проблема? Функция нуждается в указателе на строку с нулевым символом в конце. Убедитесь, что это то, что вы даете.

...