c – 来自调用者程序的库类成员错误的未定义引用
作者:互联网
其他问题在下面添加,2011年4月11日
我正在使用C开发一套跨平台的共享库DLL / Sos和测试程序集,但我必须能够支持C.这些库将仅作为目标代码发布,但测试程序将随源代码一起提供我们的客户可以拥有示例代码.出于这个原因,我正在设计要在运行时加载的库,即使用dlopen()/ LoadLibraryA()进行动态链接.
我在Umbutu 10.04上使用g 4.4.3-4,在Vista / 64上使用VC 2008(在32位模式下).
一切似乎在Windows上运行得很好(现在).但是,当我在Linux上编译时,我遇到了一些我无法弄清楚的错误.
测试器和库有几个类,分别用.cpp和.h编写.除主入口点之外,库中的类和大多数内容都在命名空间DISCOVER_NS中.
以下是该项目的简要草图:
首先,承认,我缩短了一堆名称,因此代码更具可读性.
discover.cpp
>使用指向它的指针创建一个类对象,该对象名为DiscoverObject类型的MainObject.
>有一个extern“C”函数,它将theMainObject作为void *返回给调用者程序.
> DiscoverObject有几种方法,并实例化在单独的cpp和.h中找到的其他类.一个特殊的方法名为Hello(),它可以满足您的期望,它会打印一个“hello”测试消息.
tester.cpp
>获取库的句柄
>获取返回theMainObject的函数的函数指针.
>执行函数(指针)并将返回的地址从void *转换为DISCOVER_NS :: DiscoverObject * aDiscoverObject.
>运行aDiscoverObject-> Hello().
我编译:
CC = @g
gflags = -g3
cflags = -fPIC -Wall -pedantic
lib_linkflags:= -shared -fPIC -lstdc -lrt -lpthread -rdynamic
tester_linkflags:= -ldl -lpthread
define = -D_linux_ -D_DEBUG -D_IPC_ARCH_INTEL = 1 -D_THREAD_SAFE
现在,当我编译时,我得到这些错误:
* Tester.cpp:142:未定义引用`Discover_NS :: DiscoverObject :: hello()’*
我还从discover.so中得到了一堆其他未定义的引用错误,例如:
* discover.so:未定义引用`Discover_NS :: DeviceList :: ~DeviceList()*
我尝试在SO外部“C”中制作几乎所有东西.没有不同.
我尝试将语句放入discover.cpp,如下所示:
extern void Discover_NS :: OtherClass :: method(args);
但这给了我关于“课外声明不是定义”错误的错误.
我知道这会有助于查看代码,但我需要时间来发布一些小的帖子.
谁能提出解决这个烂摊子的想法?
谢谢,
韦斯
德米特里的解决方案并不是全部解决方案,但却是解决方案中的必要元素.在检查了我的makefile后,我发现了一些无意中重复的行,我删除了这两行,以及两个“拼写错误”,其中我有错误的路径将-o编码为编译步骤.破碎的步骤编译了logger.cpp和RemException.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
然后我发现了真正的错误.我完全错过了我没有在Discover目录中编译所有.cpp的事实.花了一个小时才把所有的图片都删除了,但现在她从makefile中编译就好了.
原始问题的新版本:我知道它可以通过makefile工作,我如何让Eclipse与makefile做同样的事情?
谢谢德米特里.
韦斯
好吧,我的问题还在这里.
我有我的代码编译与Dmitry(@Dmitry)的建议.只是,它们似乎造成了一个单独的问题.我希望我的库在运行时动态链接到主测试程序.将-l Discover -l EdgeIO添加到链接会获得编译的所有内容,但它会为我提供静态链接.
仅供参考,未使用的“pi”是SO,因此SO中有一个浮点数,因此可以使用浮点支持进行编译.如果调用者想要使用浮点数,则是必需的.有没有人有更好的方法来强制g包括浮点数?
在修复了Dmitry帮助我找到的许多错误之后,我现在得到了这个输出:
make
./Discover/dllmain.cpp: In function ‘void InitalizeLibraryServices()’:
./Discover/dllmain.cpp:175: warning: unused variable ‘pi’
./EdgeIO/dllMain.cpp: In function ‘void InitalizeLibraryServices()’:
./EdgeIO/dllMain.cpp:158: warning: unused variable ‘pi’
linking RemKonTester
gflags = -g3
tstlinkflags = -ldl -lpthread
defines = -D__linux__ -D_DEBUG -D_IPC_ARCH_INTEL=1 -D_THREAD_SAFE
./RemKonTester/Debug/RemKonTester.o: In function `main':
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:81: undefined
reference to `RemKon_EdgeIO::EdgeIoObject::hello()'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:111: undefined
reference to `RemKon_Discover::DiscoverObject::hello()'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:116: undefined
reference to `RemKon_Discover::DiscoverObject::SetLogLevel(unsigned int)'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:117: undefined
reference to `RemKon_Discover::DiscoverObject::hello()'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:118: undefined
reference to `RemKon_Discover::DiscoverObject::LocalIpAddress(int)'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:122: undefined
reference to `RemKon_Discover::DiscoverObject::RegisterCallback(bool(*)
(void*), void*)'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:123: undefined
reference to `RemKon_Discover::DiscoverObject::Search()'
collect2: ld returned 1 exit status
我从Eclipse获得了同样的错误消息.
RemKonTester.cpp包含声明这些项的所有.h.我用声明extern“C”尝试过它们而不是.
希望得到帮助,
韦斯
解决方法:
您的问题似乎是-l< library>的位置:
$(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
它们应该位于目标文件之后,因为链接器在命令行遇到它们时会加载它们并搜索未定义的符号.
有关详细信息,请参阅man ld(特别是-l选项):
-l namespec
…
The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a
symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the
appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause
the linker to search the archive again.
这应该适合你:
$(CC) $(gflags) $(tstlinkflags) $(defines) -L ./Debug -o ./Debug/RemKonTester ./RemKonTester/Debug/RemKonTester.o ./RemKonTester/Debug/logger.o ./RemKonTester/Debug/libraryClass.o -ldiscover -ledgeio 2>&1 | tee ./RemKonTester/make.ERR
附:请注意,在StackOverflow中有一个用于编辑问题的选项,作为答案发布附加信息不是一个好习惯.
标签:c,cross-platform,shared-libraries,undefined-reference 来源: https://codeday.me/bug/20190903/1798089.html