我正在尝试在项目中使用avrfix library ,使用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 。在.map文件中搜索“avrfix”仅产生一行,其中提到了该行:
LOAD D:\Documents\Arduino\IMU_Kalman\avrfix\libavrfix.a
链接顺序是否可能有问题?我很茫然,这里可能出了什么问题。由于某种原因,avrfix库是否与我使用的avr-gcc编译器不兼容?我对二进制解析器也不太熟悉(或者它们甚至与我的问题无关),但是我尝试在C / C++ Build-> Settings->中选择多个不同的解析器(包括GNU Elf解析器)。项目属性中的“二进制解析器”选项卡。有关更多信息,我在github here上拥有了整个项目(尽管这是一个正在进行的工作,处于早期阶段)。我曾尝试在其他线程中寻求帮助,但似乎无法在我的应用程序中找到许多特定于avrfix库的信息。在另一个线程中,我发现了在链接器调用中使用--export-all-symbols选项的建议,但这似乎无济于事。
如果有人知道发生了什么请帮忙!请随时向我询问更多信息。
问候,
保罗
最佳答案
这是对C++
mangled name的引用。libavrfix.a
很有可能将该符号定义为未修饰的C
名称。您可以通过运行来验证
avr-readelf -Ws libavrfix.a | grep lsincoslk
如果看到
NNNN T _Z9lsincoslklPl
,我的猜测是不正确的。但是,如果您看到NNNN T lsincoslk
,那么我的猜测是正确的。查看
avrfix.h
的this version,我发现它缺少适当的extern "C"
防护措施。在将此 header 包含在C++
中时,必须执行以下操作:extern "C" {
#include "avrfix.h"
}
如果
avrfix
开发人员关心C++
,则不必这样做。您可以将补丁发送给avrfix.h
。该补丁应在开始时添加:#ifdef __cplusplus
extern "C" {
#endif
最后是这样的:
#ifdef __cplusplus
}
#endif