LINUX.ORG.RU

[C++]Переменное число аргументов в функции.

 


0

2

Есть 2 структуры:

struct nShader
{
    GLuint shaID;
    nUInt AUcnt;
    nString* AUnames;
    nByte* AUtypes;
};

struct nShaderProgram
{
    GLuint shprogID;
    nShader** shdraddrs;
    GLuint* AUindexes;
    nString* AUnames;
    nUInt AUcnt;
    nByte* AUtypes;
};
И соответствующая процедура, для линковки шейдеров в программу:

void nMakeShaderProgram(nShaderProgram* prog, nUInt amt, ...);

Первый параметр содержит адрес программы, к которой будут линковаться шейдеры, 2-ой - количество линкуемых шейдеров, остальное - адреса шейдеров. Надо из этой процедуры вытащить из шейдера (nShader) все переменные.

nShader sh1, sh2;
nShaderProgram program;
void nMakeShaderProgram(&program, 2, &sh1, &sh2);

Я пробовал получить адреса шейдеров так:

nShader* current = (nShader*)&prog+sizeof(prog)+sizeof(amt)+(sizeof(nShader*)*i);
//i - номер шейдера, отсчёт начинается с нуля.

Для последующей работы, как с обычным указателем:

current->AUcnt;
Но это не проканало, что я делаю не так?

Ответ на: комментарий от NaViKotE

>Обязательно эти va? Просто с адресами не получится?

У меня на x86 получалось вычислять адреса аргументов относительно первого. На amd64 - нет. Думаю, обязательно.

staseg ★★★★★
()
Ответ на: комментарий от staseg

>>Обязательно эти va? Просто с адресами не получится?

У меня на x86 получалось вычислять адреса аргументов относительно первого. На amd64 - нет. Думаю, обязательно.

Дело в том, что для передачи параметров могут использоваться и регистры (что и происходит на x86_64). В последнем случае нельзя реализовать va_* макросы на C (во всяком случае без использования расширений компилятора) даже зная, как происходит передача параметров в конкретной реализации. Так что надо использовать va_* макросы.

anonymous
()
Ответ на: комментарий от staseg

Можно везде, но речь идет о разных смещениях, потому необходимо писать платформенно специфичный код

vertexua ★★★★★
()

код отстой а где венгкрская нотация ? имена переменных полный бред а не имена !

anonymous
()

В общем сделал с vs_* и таки работает, как надо - шедеры линкуются.

Код:

void nMakeShaderProgram(nShaderProgram* prog, nUInt amt, ...)
{
    prog->shprogID = glCreateProgram();
    prog->AUcnt = 0;
    nUInt lastcnt = 0;
    nShader* currshader;
    prog->shdraddrs = (nShader**)malloc(sizeof(nShader*)*amt);
    va_list p;
    va_start(p, amt);
    for(nUInt i=0; i<amt; i++)
    {
        currshader = va_arg(p, nShader*);
        prog->shdraddrs[i] = currshader;
        glAttachShader(prog->shprogID, prog->shdraddrs[i]->shaID);
        lastcnt = prog->AUcnt;
        prog->AUcnt += currshader->AUcnt;
        prog->AUindexes = (nUInt*)realloc(prog->AUindexes, sizeof(nUInt)*prog->AUcnt);
        prog->AUnames = (nString*)realloc(prog->AUnames, sizeof(nString)*prog->AUcnt);
        prog->AUtypes = (nByte*)realloc(prog->AUtypes, sizeof(nByte)*prog->AUcnt);
        for(nUInt j=lastcnt; j<prog->AUcnt; j++)
        {
            strcpy(prog->AUnames[j].str, (const char*)currshader->AUnames[j-lastcnt].str);
            prog->AUtypes[j] = currshader->AUtypes[j-lastcnt];
        }
    }
    glLinkProgram(prog->shprogID);
    for(nUInt i=0; i<prog->AUcnt; i++)
    {
        if(prog->AUtypes[i] == 'a')
            prog->AUindexes[i] = glGetAttribLocation(prog->shprogID, prog->AUnames[i].str);
        else
           if(prog->AUtypes[i] == 'u')
                prog->AUindexes[i] = glGetUniformLocation(prog->shprogID, prog->AUnames[i].str);
           else
               nErr();
    }


}

NaViKotE
() автор топика

чувак, не используй va_* в С++ никогда, это как письку в вентилятор совать

shty ★★★★★
()
Ответ на: комментарий от anonymous

>void nMakeShaderProgram(nShaderProgram* prog, vector<nShader *> &shaders);

вот верно замечено. Зачем какие-то переменные параметры, когда есть векторы?

anonymous
()
Ответ на: комментарий от anonymous

Всё просто: меньше повесишь мусора - быстрее и меньше будет программа.

И ещё я недолюбливаю этот, ваш, STL.

NaViKotE
() автор топика
Ответ на: комментарий от NaViKotE

Почему? Что в этом плохого? Или так принято?

потому, что, к примеру, если я в аргументы засуну не структуру шейдера, а железную мясорубку, то твоя программа сломает себе ноги (или придётся возводить леса костылей для проверки), а по синтаксису всё будет хорошо и компилятор всё соберёт без единого варнинга

в общем случае, использование va_* приводит к нарушению type safety

имхо, гораздо лучше либо перегрузить operator<<, либо просто передавать вектор структур

shty ★★★★★
()
Ответ на: комментарий от shty

Это да, в моём случае программа должна вылететь с ошибкой сегментации, но в более серьёзных проектах такие штуки могут привести к большим проблеммам. Кстати компилятор мне варнингов не выдал. А printf, scanf, etc. тоже нарушают? И поэтому нужно cin и cout? Этого я точно делать не буду :)

NaViKotE
() автор топика
Ответ на: комментарий от anonymous

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

NaViKotE
() автор топика
Ответ на: комментарий от NaViKotE

STL не любит, потоки не любит, имена переменных не любит. Вам, батенька, надо не на С++ фигнёй маяться, а на пэхэпэ делать идиотские сайты за реальные деньги.

anonymous
()
Ответ на: комментарий от NaViKotE

Это да, в моём случае программа должна вылететь с ошибкой сегментации, но в более серьёзных проектах такие штуки могут привести к большим проблеммам.

не должна, а может, но может и не вылететь - зависит от «мясорубки», но, даже если и не вылетит, считать корректными результат работы такой программы я бы не стал

в большой программе с точки зрения операционной системы это приведёт ровно к тем же последствиям, однако потери IRL могут оказаться весьма существенными

А printf, scanf, etc. тоже нарушают?

естественно, си, вообще говоря, имеет нестрогую типизацию

shty ★★★★★
()
Ответ на: комментарий от NaViKotE

Я привёл 2 варианта с вектором и с массивом указателей. Почему не массив указателей - это логично?!

anonymous
()
Ответ на: комментарий от anonymous

он же объяснил, что это он код так оптимизирует, типа векторы и массивы у него тормозят и жрут ресурсы.

anonymous
()
Ответ на: комментарий от anonymous

> Вам, батенька, надо не на С++ фигнёй маяться, а на пэхэпэ делать идиотские сайты за реальные деньги.

согласен :)

anonymous
()
Ответ на: комментарий от anonymous

Потомучто надо ещё этот массив сначала создать, а потом удалить - затарты времени, хоть и небольшие. (Хотя это от количества шейдеров зависит).

NaViKotE
() автор топика
Ответ на: комментарий от anonymous

Ну уж нет. Я пишу этот код не денег ради (никто мне за это не платит). На линуксе играть не во что (Грубо говоря)(Хотя допустим Hedgewars - игрушка очень даже), а с костылями - противно и тормозно, вот и появилось желание что-нибудь приятное себе написать. А ещё я не люблю операторы new/delete т.к. они вызывают конструкторы - ну и? Не можете помочь? Тогда смысл вобще отвечать? Курите в сторонке, товарищь анонимус.

NaViKotE
() автор топика
Ответ на: комментарий от NaViKotE

Миллион шейдеров?! А передавать в функцию то 5, то 10, то 15 шейдеров это как? А если количество шейдеров уменьшится, переписывать код? Не любишь операторы new/delete, malloc/free? Может тебе лучше и правда писать на пехапе или питоне? Похоже ты язык не тот выбрал...

anonymous
()
Ответ на: комментарий от anonymous

Миллион спичек. Молча. А если уменьшится - это другая функция, код чего? Совсем дурак чтоле? я сказал new/delete - они вызывают конструктор и деструктор, соответственно. malloc/free/realloc только выделяют память и их я активно использую. Может тебе лучше выдалбливать надписи на мемориальных стенах? Дятел ты отменный, чесслово. Да не тот, я бы выбрал С без плюсов, если бы не шаблоный, множественное наследование, нэймспэйсы и т.д.

NaViKotE
() автор топика
Ответ на: комментарий от anonymous

Быдлокодеров много. Потомучто былдо - это группа/стадо, а кодер - это программист. Серьёзные проекты в одного не делают :)

Ну и исползуй свои STLы, new/delete и т.д. Ты думаешь я буду слушать какого-то албанца, который анонимно срёт? Адресом ошибся :D

NaViKotE
() автор топика
Ответ на: комментарий от NaViKotE

> наследование

А как наследование работает без конструкторов? Можешь привести пример кода?

anonymous
()
Ответ на: комментарий от NaViKotE

>Шаблоны, множественное наследование.

Насчёт множественного наследования я бы сильно поспорил. Шаблоны? А чем макросы не нравятся?

Booster ★★
()
Ответ на: комментарий от NaViKotE

Главное, чтобы твой говнокод не попал в какой-то серьёзный проект. На всё остальное мне наплевать.

anonymous
()
Ответ на: комментарий от anonymous

Не переживай, в серьёзный проект оно попадёт только ассемблированное :)

NaViKotE
() автор топика
Ответ на: комментарий от Booster

Хочешь сказать, что в чистом С можно так:

struct A
{
int a;
}

struct B
{
char B;
}

struct C: public A, B;
Если да, то я рад за С.

Заменить шаблоны классами? Ну и как ты предлогаешь это сделать? Например в этом случае:

template <typename tF, typename tS> void proc_name(tF Fo, tS So);

P.S. Возможно сейчас я спрашиваю очевидное, но мне на столько хочется спать, что очевидное мне таким не кажется...

NaViKotE
() автор топика
Ответ на: комментарий от NaViKotE

Школота детектед. И вообще, настоящий asm программист напишет asm программу на любом ЯП!

Gorthauer ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.