va_args and 64 bits

64-bit, c++, linux, printf

Solution

Change

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

to

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

and it should work without the cast.

Problem

I'm the lead dev for Bitfighter, and am having problems porting the game to 64-bit Linux. This should be a relatively easy and common problem, but it has stumped a number of people and I have been able to find no good information about it. [[ The code compiles in 32-bit with gcc version 4.1.2, and others, and fails with several variants of 64-bit Linux, but I am relying on reports from others, and do not have the exact version of gcc that is failing. But it is failing for several people, on a variety of Linux flavors. I am 99% sure this is not a compiler version issue. ]] I have the following: ``` 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); } ``` This works great on 32-bit platforms. However, when I compile it on 64-bit Linux, it fails: ``` 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*)' ``` I've tried many variants, including: ``` return vsnprintf(buffer, bufferSize, format, (va_list) arglist); ``` without success. Does anyone have any ideas on how to make this construct portable, or achieve the same ends with a more 64-bit friendly mechanism? And, for bonus points :-) can anyone tell me where the va_list_tag thingy comes from? Thanks! ============================================ Here is the solution we settled on, using a different example: ``` logprintf("Hello %s", name); ``` calls ``` void logprintf(const char *format, ...) { va_list s; va_start( s, format ); logger(LogConsumer::GeneralFilter, format, s); va_end(s); } ``` calls ``` void logger(LogConsumer::FilterType filtertype, const char *format, va_list args) { char buffer[4096]; vsnprintf(buffer, sizeof(buffer), format, args); Platform::outputDebugString(buffer); } ```

Original source