C++ 调用程序中对库类成员的未定义引用错误
以下新增问题,2011年11月4日 <>我正在开发一个跨平台的共享库DLLS/SOS和TealC++程序,虽然我必须能够支持C。这些库只作为目标代码,但是测试程序会与源一起传送,这样我们的客户可以有示例代码。出于这个原因,我正在设计要在运行时加载的库,即使用dlopen()/LoadLibraryA()进行动态链接 我在Umbutu 10.04上使用g++4.4.3-4,在Vista/64上使用VC++2008(32位模式) 在Windows上(现在)一切似乎都很好。然而,当我在Linux上编译时,我得到了一些我无法理解的错误 测试仪和库中有几个用.cpp和.h编码的类。库中的类和除主入口点之外的大部分内容都位于名称空间中 以下是该项目的简要示意图: 首先,我承认,我缩短了一堆名字,这样代码就更可读了 discover.cppC++ 调用程序中对库类成员的未定义引用错误,c++,cross-platform,shared-libraries,undefined-reference,C++,Cross Platform,Shared Libraries,Undefined Reference,以下新增问题,2011年11月4日 我正在开发一个跨平台的共享库DLLS/SOS和TealC++程序,虽然我必须能够支持C。这些库只作为目标代码,但是测试程序会与源一起传送,这样我们的客户可以有示例代码。出于这个原因,我正在设计要在运行时加载的库,即使用dlopen()/LoadLibraryA()进行动态链接 我在Umbutu 10.04上使用g++4.4.3-4,在Vista/64上使用VC++2008(32位模式) 在Windows上(现在)一切似乎都很好。然而,当我在Linux上编译时,
- 创建一个类对象,该类对象带有指向它的指针,称为DiscoverObject类型的主对象
- 具有一个外部“C”函数,该函数将主对象作为void*返回给调用程序
- DiscoverObject有几个方法,并实例化在单独的cpp和.h中找到的其他类。一个特殊的方法名为Hello(),它完成了您所期望的功能,它打印一条“Hello”测试消息
测试仪.cpp
- 获取库的句柄
- 获取指向返回主对象的函数的函数指针
- 执行函数(指针)并将返回的地址从void*强制转换为DISCOVER\NS::DiscoverObject*aDiscoverObject
- 运行aDiscoverObject->Hello()
我编译时使用: CC=@g++ gflags=-g3 cflags=-fPIC-Wall-pedantic lib_linkflags:=-shared-fPIC-lstdc++-lrt-lpthread-rdynamic 测试仪链接标志:=-ldl-lpthread defines=-D\u linux\ud\u DEBUG-D\u IPC\u ARCH\u INTEL=1-D\u THREAD\u SAFE
现在,当我编译时,会出现以下错误: *Tester.cpp:142:Discover\NS::DiscoverObject::hello()的未定义引用* 我还从discover中获得了一系列其他未定义的引用错误。例如: *discover.so:discover\n NS::DeviceList::~DeviceList()的未定义引用*
我尝试过用所谓的外部“C”来制作几乎所有的东西。没有区别 我尝试将语句放入discover.cpp,如下所示: extern void Discover_NS::OtherClass::method(args); 但这给了我关于“类外声明不是定义”错误的错误
我知道看到代码会有帮助,但我需要时间来找出一些小东西来发布 有人能提出解决这一混乱局面的办法吗 谢谢 韦斯 Dmitry的解决方案并不是全部修复方案,而是解决方案中的一个必要元素。在检查我的makefile时,我发现了一些无意中重复的行,我删除了这些行,还有两个“输入错误”,其中-o的路径被错误地编码到编译步骤中。logger.cpp和RemeException.cpp编译的中断步骤:
./common/logger.o : ./common/logger.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common
-I ./EdgeIO -I ./Discover
-o ./common/Debug/logger.o <+++++++++ path to .o was wrong
./common/logger.cpp 2>&1 | tee ./RemKonTester/logger.ERR
我从Eclipse获得了相同的错误消息集
RemKonTester.cpp包括声明这些项目的所有.h。我已经用声明extern“C”试过了,没有
希望得到帮助
韦斯编辑:终于找到了“编辑”。让它更漂亮。wjm 抱歉耽搁了。昨晚我不得不把一棵倒下的树从我的前院弄出来 注意:我更改了原始注释中的一些名称,使其更短。这个答案把一切都说清楚了
g++输出
$ make
./EdgeIO/dllMain.cpp: In function ‘void InitalizeLibraryServices()’:
./EdgeIO/dllMain.cpp:158: warning: unused variable ‘pi’
./Discover/dllmain.cpp: In function ‘void InitalizeLibraryServices()’:
./Discover/dllmain.cpp:174: warning: unused variable ‘pi’
./RemKonTester/RemKonTester.cpp: In function ‘int main(int, char**)’:
./RemKonTester/RemKonTester.cpp:130: warning: ISO C++ forbids casting between
pointer-to-function and pointer-to-object
./RemKonTester/RemKonTester.cpp:152: warning: unused variable ‘searchResp’
./RemKonTester/libraryClass.cpp: In member function ‘int
library::AttachLibrary()’:
./RemKonTester/libraryClass.cpp:132: warning: ISO C++ forbids casting between
pointer-to-function and pointer-to-object
./RemKonTester/libraryClass.cpp:154: warning: ISO C++ forbids casting between
pointer-to-function and pointer-to-object
./RemKonTester/Debug/RemKonTester.o: In function `main':
/home/wmiller/Projects/Eclipse/
./RemKonTester/RemKonTester.cpp:142: undefined reference to
`RemKon_Discover::DiscoverObject::hello()'
collect2: ld returned 1 exit status
gflags = -g3
tstlinkflags = -ldl -lpthread
defines = -D__linux__ -D_DEBUG -D_IPC_ARCH_INTEL=1 -D_THREAD_SAFE
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemKonDeviceList::~RemKonDeviceList()'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::ClientPort(unsigned short)'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::PayloadSize(unsigned int)'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::Socket() const'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemKonDeviceList::Count() const'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemException::~RemException()'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::UDPbinder()'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::ListenTimeOut(int)'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::ServerPort(unsigned short)'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemKonDeviceList::Next()'
./Debug/libdiscover.so: undefined reference to `RemKon_Discover::Log(char
const*, ...)'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::UDPlisten(unsigned char*, int*, sockaddr_in*, int*)'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemException::RemException()'
./Debug/libdiscover.so: undefined reference to `RemKon_Discover::VerboseLogging()'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::RegisterCallbackFunction(void (*)(void*, unsigned
char*, int), void*)'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemKonDeviceList::First()'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::TestData(unsigned int, unsigned int, unsigned char*,
unsigned int)'
./Debug/libdiscover.so: undefined reference to `RemKon_Discover::Logging()'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::MessageLength(int)'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::LocalIpAddress(int)'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::UDPsend()'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::DiscoverObject::LocalIpAddress() const'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::SetBroadcastMode()'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::MakeMacAddressString(unsigned char*, char*)'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemKonDeviceList::RemKonDeviceList()'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemKonDeviceList::New()'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::ActivateLogging(unsigned int)'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::RemSocket()'
./Debug/libdiscover.so: undefined reference to
`RemKon_Discover::RemSocket::Payload(unsigned int)'
collect2: ld returned 1 exit status
这是makefile。抱歉,我不太会说make,所以makefile是功能性的,不美观
CC = @g++
gflags = -g3
cflags = -fPIC -Wall -pedantic
liblinkflags := -shared -fPIC -lstdc++ -lrt -lpthread -rdynamic
tstlinkflags := -ldl -lpthread
defines = -D__linux__ -D_DEBUG -D_IPC_ARCH_INTEL=1 -D_THREAD_SAFE
all : clean edgeio discover tester
############################################
edgeio : ./EdgeIO/dllMain.o ./EdgeIO/EdgeIO.o
$(CC) $(gflags) $(liblinkflags) $(defines) -Wl,-soname,./Debug
/libedgeio.so.1 -o ./Debug/libedgeio.so.1.0 ./EdgeIO/Debug/edgeio.o
./EdgeIO/Debug/dllmain.o 2>&1 | tee ./EdgeIO/make.ERR
@cd ./Debug; ln -sf libedgeio.so.1.0 libedgeio.so
@cd ./Debug; ln -sf libedgeio.so.1.0 libedgeio.so.1
./EdgeIO/dllMain.o : ./EdgeIO/dllMain.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o./EdgeIO/Debug/dllmain.o ./EdgeIO/dllMain.cpp 2>&1
| tee ./EdgeIO/dllmain.ERR
./EdgeIO/EdgeIO.o : ./EdgeIO/EdgeIO.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o./EdgeIO/Debug/edgeio.o ./EdgeIO/EdgeIO.cpp 2>&1 |
tee ./EdgeIO/EdgeIO.ERR
############################################
discover : ./Discover/Discover.o ./Discover/dllmain.o
$(CC) $(gflags) $(liblinkflags) $(defines) -Wl,-soname,./Debug
/libdiscover.so.1 -o ./Debug/libdiscover.so.1.0 ./Discover/Debug
/Discover.o ./Discover/Debug/dllmain.o 2>&1 | tee ./Discover/make.ERR
@cd ./Debug; ln -sf libdiscover.so.1.0 libdiscover.so
@cd ./Debug; ln -sf libdiscover.so.1.0 libdiscover.so.1
./Discover/Discover.o : ./Discover/Discover.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o./Discover/Debug/Discover.o ./Discover/Discover.cpp
2>&1 | tee ./Discover/Discover.ERR
./Discover/dllmain.o : ./Discover/dllmain.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o./Discover/Debug/dllmain.o ./Discover/dllmain.cpp
2>&1 | tee ./Discover/dllmain.ERR
############################################
tester : ./RemKonTester/RemKonTester.o ./common/logger.o ./RemKonTester
/libraryClass.o ./common/RemException.o
$(CC) $(gflags) $(tstlinkflags) $(defines)
-L ./Debug -o ./Debug/RemKonTester ./RemKonTester/Debug
/RemKonTester.o ./RemKonTester/Debug/logger.o ./RemKonTester/Debug
/libraryClass.o 2>&1 | tee ./RemKonTester/make.ERR
@echo "gflags = $(gflags)" 2>&1 | tee ./RemKonTester/make.ERR
@echo "tstlinkflags = $(tstlinkflags)" 2>&1 | tee ./RemKonTester/make.ERR
@echo "defines = $(defines)" 2>&1 | tee ./RemKonTester/make.ERR
$(CC) $(gflags) $(tstlinkflags) $(defines) -L ./Debug -ldiscover
-ledgeio -o ./Debug/RemKonTester ./RemKonTester/Debug/RemKonTester.o
./RemKonTester/Debug/logger.o ./RemKonTester/Debug/libraryClass.o
2>&1 | tee ./RemKonTester/make.ERR
./RemKonTester/RemKonTester.o : ./RemKonTester/RemKonTester.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o ./RemKonTester/Debug/RemKonTester.o ./RemKonTester
/RemKonTester.cpp 2>&1 | tee ./RemKonTester/RemKonTester.ERR
./common/logger.o : ./common/logger.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o ./RemKonTester/Debug/logger.o ./common/logger.cpp
2>&1 | tee ./RemKonTester/logger.ERR
./RemKonTester/libraryClass.o : ./RemKonTester/libraryClass.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o ./RemKonTester/Debug/libraryClass.o
./RemKonTester/libraryClass.cpp 2>&1 | tee ./RemKonTester
/libraryClass.ERR
./common/RemException.o : ./common/RemException.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o ./RemKonTester/Debug/RemException.o ./common
/RemException.cpp 2>&1 | tee ./RemKonTester/RemException.ERR
############################################
clean :
@rm -f *.ERR
@rm -f ./common/*.ERR
@rm -f ./EdgeIO/*.ERR
@rm -f ./Discover/*.ERR
@rm -f ./RemKonTester/*.ERR
@rm -f QEMACRO*
@rm -f ./common/EdgeIO/QEMACRO*
@rm -f ./EdgeIO/QEMACRO*
@rm -f ./Discover/QEMACRO*
@rm -f ./RemKonTester/QEMACRO*
@rm -f ./Debug/*.o
@rm -f ./common/Debug/*.o
@rm -f ./EdgeIO/Debug/*.o
@rm -f ./Discover/Debug/*.o
@rm -f ./RemKonTester/Debug/*.o
@rm -f ./Debug/*.log
@rm -f ./common/Debug/*.log
@rm -f ./EdgeIO/Debug/*.log
@rm -f ./Discover/Debug/*.log
@rm -f ./RemKonTester/Debug/*.log
@rm -f ./Debug/*.so*
############################################
谢谢
Wes您的问题似乎是
-l
的位置:
它们应该在对象文件之后,因为链接器在命令行遇到它们时加载它们,并搜索未定义的符号
有关更多信息,请参见man-ld
(特别是-l
选项):
-l名称规范
链接器将只在命令行上指定的位置搜索存档一次。如果存档定义了
在命令行存档之前出现的某个对象中未定义的符号,链接器将包括
存档中的适当文件。但是,稍后出现在命令行上的对象中的未定义符号不会导致
重新搜索存档的链接器
这应该适合您:
$(CC)$(gflags)$(tstlinkflags)$(定义)-L./Debug-o./Debug/RemKonTester./RemKonTester/Debug/RemKonTester.o./RemKonTester/Debug/logger.o./RemKonTester/Debug/libraryClass.o-ldiscover-legio2>&1 | tee./RemKonTester/make.ERR
请注意,StackOverflow中有一个编辑问题的选项,将其他信息作为答案发布不是一个好做法。您可以发布g++的实际输出吗?通常问题是在给g++的参数的顺序上。同样,给g++的具体参数也不是很清楚:)请尝试
make-n
查看make执行的实际g++命令,并将它们发布到此处。还可以使用nm lib\u your\u lib进行检查。因此,在\u you\u lib
中添加一些\u symbol\u,以确保预期的符号实际上在库中
CC = @g++
gflags = -g3
cflags = -fPIC -Wall -pedantic
liblinkflags := -shared -fPIC -lstdc++ -lrt -lpthread -rdynamic
tstlinkflags := -ldl -lpthread
defines = -D__linux__ -D_DEBUG -D_IPC_ARCH_INTEL=1 -D_THREAD_SAFE
all : clean edgeio discover tester
############################################
edgeio : ./EdgeIO/dllMain.o ./EdgeIO/EdgeIO.o
$(CC) $(gflags) $(liblinkflags) $(defines) -Wl,-soname,./Debug
/libedgeio.so.1 -o ./Debug/libedgeio.so.1.0 ./EdgeIO/Debug/edgeio.o
./EdgeIO/Debug/dllmain.o 2>&1 | tee ./EdgeIO/make.ERR
@cd ./Debug; ln -sf libedgeio.so.1.0 libedgeio.so
@cd ./Debug; ln -sf libedgeio.so.1.0 libedgeio.so.1
./EdgeIO/dllMain.o : ./EdgeIO/dllMain.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o./EdgeIO/Debug/dllmain.o ./EdgeIO/dllMain.cpp 2>&1
| tee ./EdgeIO/dllmain.ERR
./EdgeIO/EdgeIO.o : ./EdgeIO/EdgeIO.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o./EdgeIO/Debug/edgeio.o ./EdgeIO/EdgeIO.cpp 2>&1 |
tee ./EdgeIO/EdgeIO.ERR
############################################
discover : ./Discover/Discover.o ./Discover/dllmain.o
$(CC) $(gflags) $(liblinkflags) $(defines) -Wl,-soname,./Debug
/libdiscover.so.1 -o ./Debug/libdiscover.so.1.0 ./Discover/Debug
/Discover.o ./Discover/Debug/dllmain.o 2>&1 | tee ./Discover/make.ERR
@cd ./Debug; ln -sf libdiscover.so.1.0 libdiscover.so
@cd ./Debug; ln -sf libdiscover.so.1.0 libdiscover.so.1
./Discover/Discover.o : ./Discover/Discover.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o./Discover/Debug/Discover.o ./Discover/Discover.cpp
2>&1 | tee ./Discover/Discover.ERR
./Discover/dllmain.o : ./Discover/dllmain.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o./Discover/Debug/dllmain.o ./Discover/dllmain.cpp
2>&1 | tee ./Discover/dllmain.ERR
############################################
tester : ./RemKonTester/RemKonTester.o ./common/logger.o ./RemKonTester
/libraryClass.o ./common/RemException.o
$(CC) $(gflags) $(tstlinkflags) $(defines)
-L ./Debug -o ./Debug/RemKonTester ./RemKonTester/Debug
/RemKonTester.o ./RemKonTester/Debug/logger.o ./RemKonTester/Debug
/libraryClass.o 2>&1 | tee ./RemKonTester/make.ERR
@echo "gflags = $(gflags)" 2>&1 | tee ./RemKonTester/make.ERR
@echo "tstlinkflags = $(tstlinkflags)" 2>&1 | tee ./RemKonTester/make.ERR
@echo "defines = $(defines)" 2>&1 | tee ./RemKonTester/make.ERR
$(CC) $(gflags) $(tstlinkflags) $(defines) -L ./Debug -ldiscover
-ledgeio -o ./Debug/RemKonTester ./RemKonTester/Debug/RemKonTester.o
./RemKonTester/Debug/logger.o ./RemKonTester/Debug/libraryClass.o
2>&1 | tee ./RemKonTester/make.ERR
./RemKonTester/RemKonTester.o : ./RemKonTester/RemKonTester.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o ./RemKonTester/Debug/RemKonTester.o ./RemKonTester
/RemKonTester.cpp 2>&1 | tee ./RemKonTester/RemKonTester.ERR
./common/logger.o : ./common/logger.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o ./RemKonTester/Debug/logger.o ./common/logger.cpp
2>&1 | tee ./RemKonTester/logger.ERR
./RemKonTester/libraryClass.o : ./RemKonTester/libraryClass.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o ./RemKonTester/Debug/libraryClass.o
./RemKonTester/libraryClass.cpp 2>&1 | tee ./RemKonTester
/libraryClass.ERR
./common/RemException.o : ./common/RemException.cpp
$(CC) $(gflags) $(cflags) -c $(defines) -I ./common -I ./EdgeIO
-I ./Discover -o ./RemKonTester/Debug/RemException.o ./common
/RemException.cpp 2>&1 | tee ./RemKonTester/RemException.ERR
############################################
clean :
@rm -f *.ERR
@rm -f ./common/*.ERR
@rm -f ./EdgeIO/*.ERR
@rm -f ./Discover/*.ERR
@rm -f ./RemKonTester/*.ERR
@rm -f QEMACRO*
@rm -f ./common/EdgeIO/QEMACRO*
@rm -f ./EdgeIO/QEMACRO*
@rm -f ./Discover/QEMACRO*
@rm -f ./RemKonTester/QEMACRO*
@rm -f ./Debug/*.o
@rm -f ./common/Debug/*.o
@rm -f ./EdgeIO/Debug/*.o
@rm -f ./Discover/Debug/*.o
@rm -f ./RemKonTester/Debug/*.o
@rm -f ./Debug/*.log
@rm -f ./common/Debug/*.log
@rm -f ./EdgeIO/Debug/*.log
@rm -f ./Discover/Debug/*.log
@rm -f ./RemKonTester/Debug/*.log
@rm -f ./Debug/*.so*
############################################
$(CC) $(gflags) $(tstlinkflags) $(defines) -L ./Debug -ldiscover
-ledgeio -o ./Debug/RemKonTester ./RemKonTester/Debug/RemKonTester.o
./RemKonTester/Debug/logger.o ./RemKonTester/Debug/libraryClass.o
2>&1 | tee ./RemKonTester/make.ERR