2

我正在尝试在项目中使用avrfix 库,使用 Eclipse (v4.2.2) 作为 IDE,使用 avr-gcc 作为编译器。头文件 (avrfix.h) 和库文件 (libavrfix.a) 都包含在同一目录中,该目录位于项目的搜索路径以及链接器的库搜索路径中。编译时,我收到以下错误:

D:\Documents\Arduino\IMU_Kalman\Release/../HMC5883/HMC5883.cpp:359: undefined reference to `lsincoslk(long, long*)'
D:\Documents\Arduino\IMU_Kalman\Release/../HMC5883/HMC5883.cpp:360: undefined reference to `lsincoslk(long, long*)'
D:\Documents\Arduino\IMU_Kalman\Release/../HMC5883/HMC5883.cpp:361: undefined reference to `lmullkD(long, long)'
D:\Documents\Arduino\IMU_Kalman\Release/../HMC5883/HMC5883.cpp:362: undefined reference to `lmullkD(long, long)'
D:\Documents\Arduino\IMU_Kalman\Release/../HMC5883/HMC5883.cpp:365: undefined reference to `lmullkD(long, long)'
D:\Documents\Arduino\IMU_Kalman\Release/../HMC5883/HMC5883.cpp:365: undefined reference to `lmullkD(long, long)'
D:\Documents\Arduino\IMU_Kalman\Release/../HMC5883/HMC5883.cpp:365: undefined reference to `lmullkD(long, long)'
./HMC5883/HMC5883.o:D:\Documents\Arduino\IMU_Kalman\Release/../HMC5883/HMC5883.cpp:367: more undefined references to `lmullkD(long, long)' follow
./HMC5883/HMC5883.o: In function `HMC5883::Calc_Heading(long, long)':
D:\Documents\Arduino\IMU_Kalman\Release/../HMC5883/HMC5883.cpp:369: undefined reference to `latan2lk(long, long)'
make: *** [IMU_Kalman.elf] Error 1

我知道这意味着链接器没有正确找到和链接有问题的函数(lsincoslk、lmullkD、latan2lk)。这些函数应该位于 avrfix 库中。为了完整起见,这里是使用的链接器调用:

avr-gcc -Os -Wl,--gc-sections  -Wl,-Map,"IMU_Kalman.map",--cref --export-all-symbols -L"D:\Documents\Arduino\IMU_Kalman\avrfix" -L"D:\Documents\Arduino\IMU_Kalman\Board_Support_Library" -mmcu=atmega328p  -o"IMU_Kalman.elf"  ./Wire/Wire.o ./Wire/twi.o  ./SPI/SPI.o  ./MPU6000/MPU6000.o  ./Kalman_Filters/GyroKalman.o  ./HMC5883/HMC5883.o  ./GlobalVariables.o ./IMU_Kalman.o   -lavrfix -lArduino_Duemilanove_w__ATmega328 -lm

这里的重要部分是包含 -lavrfix 命令。我知道链接器能够找到该库,因为如果我尝试拼写错误的 avrfix,它会给出一个错误,即它找不到该库,而不是上面提到的那些。还值得一提的是,我使用我认为相同的方法成功地包含了 libArduino_Duemilanove_w__ATmega328.a 库。

当我查看编译器生成的 .map 文件时,我确实看到了来自 Arduino_Duemilanove_w__ATmega328 库的几个函数,正如预期的那样(例如 malloc)。但是,avrfix 库中的任何函数或对象似乎都没有进入映射。在 .map 文件中搜索 'avrfix' 只会产生一行提到它的地方:

LOAD D:\Documents\Arduino\IMU_Kalman\avrfix\libavrfix.a

链接顺序可能有问题吗?我不知道这里可能出了什么问题。avrfix 库是否与我正在使用的 avr-gcc 编译器不兼容?我对二进制解析器也有点不熟悉(或者它们甚至与我的问题有关),但我尝试在 C/C++ Build->Settings-> 中选择多个不同的解析器(包括 GNU Elf Parser)项目属性中的二进制解析器选项卡。欲了解更多信息,我在github 上有整个项目(尽管它正在进行中,处于早期阶段). 我尝试在其他线程中寻求帮助,但似乎无法在我的应用程序中找到很多特定于 avrfix 库的信息。在另一个线程中,我发现了在链接器调用中使用 --export-all-symbols 选项的建议,但这似乎对我的情况没有帮助。

如果有人知道发生了什么,请帮忙!不要犹豫,向我索取更多信息。

问候,

保罗

4

1 回答 1

4

未定义对 `lsincoslk(long, long*)' 的引用

这是对C++ mangled name的引用。

很可能该libavrfix.a符号定义为未修饰 C的名称。您可以通过运行来验证这一点

avr-readelf -Ws libavrfix.a | grep lsincoslk

如果你看到NNNN T _Z9lsincoslklPl了,我的猜测是不正确的。但如果你看到NNNN T lsincoslk了,那么我的猜测是正确的。

查看这个版本avrfix.h,我发现它缺乏适当的extern "C"保护。当您将此标头包含到C++中时,您必须执行以下操作:

extern "C" {
#include "avrfix.h"
}

如果avrfix开发人员关心C++. 您可以将补丁发送到avrfix.h. 补丁应该在开头添加这个:

#ifdef __cplusplus
extern "C" {
#endif

最后是:

#ifdef __cplusplus
}
#endif
于 2013-08-31T23:15:26.523 回答