va_args и 64 бита - PullRequest
       12

va_args и 64 бита

3 голосов
/ 26 января 2010

Я ведущий разработчик Bitfighter , и у меня проблемы с переносом игры на 64-битный Linux. Это должно быть относительно простой и распространенной проблемой, но это поставило многих в тупик, и я не смог найти никакой хорошей информации об этом.

[[Код компилируется в 32-битной версии gcc 4.1.2 и др. И не работает с несколькими вариантами 64-битной Linux, но я полагаюсь на отчеты других и не имею точной версии GCC, который терпит неудачу. Но он не работает для нескольких людей на разных вкусах Linux. Я на 99% уверен, что это не проблема версии компилятора. ]]

У меня есть следующее:

 void UserInterface::drawCenteredString(int y, int size, const char *format, ...)
   {
    va_list args; 
    va_start(args, format); 
    char buffer[2048]; 
    dVsprintf(buffer, sizeof(buffer), format, args); 
    va_end(args);

    drawCenteredString2(y, size, buffer);
 }   

 // Elsewhere, in platform.cpp... (this is where the error occurs)

 S32 dVsprintf(char *buffer, int bufferSize, const char *format, void *arglist)
 {
    return vsnprintf(buffer, bufferSize, format, (char *) arglist);
 }

Отлично работает на 32-битных платформах. Однако, когда я компилирую его на 64-битном Linux, он терпит неудачу:

 platform.cpp:457: error: cannot convert 'char*' to '__va_list_tag*' for argument '4' to 'int TNL::vsnprintf(char*, size_t, const char*, __va_list_tag*)'

Я пробовал много вариантов, в том числе:

return vsnprintf(buffer, bufferSize, format, (va_list) arglist);

без успеха.

У кого-нибудь есть идеи о том, как сделать эту конструкцию переносимой или достичь тех же целей с помощью более 64-битного дружественного механизма?

А что касается бонусных баллов :-) Может кто-нибудь сказать мне, откуда взялась вещь va_list_tag?

Спасибо!

============================================

Вот решение, на котором мы остановились, используя другой пример:

logprintf("Hello %s", name);

называет

void logprintf(const char *format, ...)
{
   va_list s;    
   va_start( s, format );

   logger(LogConsumer::GeneralFilter, format, s);
   va_end(s);
}

звонки

void logger(LogConsumer::FilterType filtertype, const char *format, va_list args)
{
   char buffer[4096];

   vsnprintf(buffer, sizeof(buffer), format, args);

   Platform::outputDebugString(buffer);
}

Ответы [ 4 ]

5 голосов
/ 26 января 2010

Изменение

S32 dVsprintf(char *buffer, int bufferSize, const char *format, void *arglist)

до

S32 dVsprintf(char *buffer, size_t bufferSize, const char *format, va_list arglist)

и должно работать без приведения.

3 голосов
/ 26 января 2010

Во-первых, прототип вашего dVsprintf неверен.

S32 dVsprintf(char *buffer, int bufferSize, const char *format, void *arglist)

arglist явно имеет тип va_list из контекста.

Во-вторых, почему бы просто не использовать vsnprintf вместо вызова dVsprintf?

В-третьих, ваша функция drawCenteredString явно бесконечно повторяется, что нехорошо:

void UserInterface::drawCenteredString(int y, int size, const char *format, ...)
{
    ///...
    drawCenteredString(y, size, buffer);
}   

__va_list_tag* должен быть базовым типом va_list. Это трудно проверить, поскольку va_list зависит от реализации gcc и, насколько я вижу, не определен в системных заголовочных файлах.

2 голосов
/ 26 января 2010

Это должно работать:

S32 dVsprintf(char *buffer, int bufferSize, const char *format, ...)
{
    va_list va_args;
    va_start( va_args, format );
    S32 result = vsnprintf(buffer, bufferSize, format, va_args); 
    va_end( va_args );
    return result;
}

__va_list_tag* - это скрытый тип реализации ..., поэтому ему не понравился тип char* - внезапно указатель перестал быть 32-битным ...

Учитывая, что это C ++, вы рассматривали более подход C ++, чем va_args? На ум приходит несколько идей:

0 голосов
/ 01 мая 2016

В моем случае переименование stdarg.h в out ... osprey / obj / include, fix_starg.h, soved для выдачи и, конечно, заголовок, требующий stdarg.h, также необходимо отредактировать в: #include , Видимо, stdarg.h, сидящий снаружи ... kernel / obj / include создавал конфликт в бионическом режиме. Я заметил эту проблему с несколькими заголовочными файлами (в частности, types.h и аналогичными вариантами). Заголовки в ядре / include и в бионическом виде выглядят нормально, но как только они находятся в kernel / obj / incudes или kernel / obj / includes / linux, это может создать проблему. Я предполагаю, что эта папка обрабатывается по-другому, по крайней мере, она, кажется, создает хаос в бионическом. Переименование заголовочных файлов, похоже, решило проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...