我是Bitfighter的首席开发者,并且在将游戏移植到64位Linux时遇到了问题。这应该是一个相对容易和常见的问题,但它已经困扰了许多人,我找不到有关它的好信息。
[[代码用gcc版本4.1.2和其他代码编译32位,并且有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 thingy来自哪里?
谢谢!
============================================
以下是我们解决的解决方案,使用了另一个例子:
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);
}
答案 0 :(得分:5)
更改
S32 dVsprintf(char *buffer, int bufferSize, const char *format, void *arglist)
到
S32 dVsprintf(char *buffer, size_t bufferSize, const char *format, va_list arglist)
并且它应该在没有演员的情况下工作。
答案 1 :(得分:3)
首先,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 :(得分:2)
这应该有效:
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 ++,您是否考虑过比va_args更多的C ++方法?想到了几个想法:
<<
运算符进行格式化答案 3 :(得分:0)
在我的情况下,重命名stdarg.h在... osprey / obj / include,到fix_starg.h,soved发布,当然需要stdarg.h的标题也需要编辑为:#include 。显然stdarg.h坐在外面...... kernel / obj / include正在创建一个仿生冲突。我已经注意到这个问题有几个头文件(特别是types.h和类似的变体)。内核/包含和仿生中的标题似乎很好但是只要在kernel / obj / incudes或kernel / obj / includes / linux中,它似乎就会产生问题。我猜这个文件夹的处理方式不同,至少它似乎在仿生中造成了破坏。重命名头文件似乎解决了这个问题。