需要编译一个UEFI下的应用程序,需要用到StdLib, 但使用VS2017 + edk2201905 或edk2-vUDK2018都编译不通过, 一直提示:LibGdtoa.lib(ldtoa.obj) : error LNK2001: 无法解析的外部符号 ___fpclassifyd。
查看发现是ldtoa.c调用math.h, 在math.h中有声明:
/*
Library implementation
*/
int __fpclassifyf(float);
int __fpclassifyd(double);
其它类似函数在LibC\Main下都有实现,但__fpclassifyf和__fpclassifyd没有实现。 所以手动实现这两个函数。 参照其它类似函数,将这个实现文件放在Main目录下编译进LibC(中间走了许多弯路,最后才发现只需要放在Main下,编译进LibC库就可以).
源文件参考了资源1, 实际只需要实现__fpclassifyf(float)和__fpclassifyd(double)。 在LibC.inf中,在[Sources]添加此文件 Main/fpclassify.c。
/* fpclassify.c */
#include <sys/types.h>
#include <math.h>
#include <machine/ieee.h>
union float_u {
float f;
struct ieee_single bits;
};
union double_u {
double d;
struct ieee_double bits;
};
int __fpclassifyd(double d){
union double_u u;
u.d=d;
if(u.bits.dbl_exp==0){
return ((u.bits.dbl_fracl | u.bits.dbl_frach)==0)?FP_ZERO : FP_SUBNORMAL;
}
if(u.bits.dbl_exp == DBL_EXP_INFNAN){
return ((u.bits.dbl_fracl | u.bits.dbl_frach)==0) ?FP_INFINITE : FP_NAN;
}
return FP_NORMAL;
}
int __fpclassifyf(float f ){
union float_u u;
u.f=f;
if(u.bits.sng_exp == 0) {
return (u.bits.sng_frac == 0 )? FP_ZERO : FP_SUBNORMAL;
}
if(u.bits.sng_exp==SNG_EXP_INFNAN){
return (u.bits.sng_frac == 0)? FP_INFINITE : FP_NAN;
}
return FP_NORMAL;
}
int __isinf(double d){
return (__fpclassifyd(d) == FP_INFINITE);
}
int __isnan(double d) {
return (__fpclassifyd(d) == FP_NAN);
}
int __isfinite(double d) {
int type = __fpclassifyd(d);
return ((type != FP_NAN) && (type != FP_INFINITE));
}
int __isfinitef(float f) {
int type = __fpclassifyf(f);
return ((type != FP_NAN) && (type != FP_INFINITE));
}
int __isnormal(double d) {
return (__fpclassifyd(d) == FP_NORMAL);
}
int __isnormalf(float f) {
return (__fpclassifyf(f) == FP_NORMAL);
}
#ifdef __HAVE_LONG_DOUBLE
union long_double_u {
long double ld;
struct ieee_ext bits;
};
#define zero_frac(b) ((b.ext_fracl | b.ext_frach ) == 0)
int __fpclassifyl(long double ld) {
union long_double_u u;
u.ld = ld;
if (u.bits.ext_exp == 0) {
return zero_frac(u.bits) ? FP_ZERO : FP_SUBNORMAL;
}
if (u.bits.ext_exp == EXT_EXP_INFNAN) {
return zero_frac(u.bits) ? FP_INFINITE : FP_NAN;
}
return FP_NORMAL;
}
int __isfinitel(long double ld) {
int type = __fpclassifyl(ld);
return ((type != FP_NAN) && (type != FP_INFINITE));
}
int __isnormall(long double ld) {
return (__fpclassifyl(ld) == FP_NORMAL);
}
#endif