下面添加的其他问题,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
定义= -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 添加到链接中可以编译所有内容,但它会为我提供静态链接。
FYI,未使用的“pi”是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”尝试了它们而不是。
希望得到帮助,
韦斯
答案 0 :(得分:5)
您的问题似乎是-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
...
链接器将仅在命令行上指定的位置搜索一次存档。如果存档定义了 在命令行中存档之前出现的某个对象中未定义的符号,链接器将包含 存档中的相应文件。但是,稍后在命令行中出现的对象中的未定义符号将不会导致 链接器再次搜索存档。
这应该适合你:
$(CC)$(gflags)$(tstlinkflags)$(定义)-L ./Debug -o ./Debug/RemKonTester ./RemKonTester/Debug/RemKonTester.o ./RemKonTester/Debug/logger.o。 /RemKonTester/Debug/libraryClass.o -ldiscover -ledgeio 2&gt;&amp; 1 | tee ./RemKonTester/make.ERR
P.S。请注意,在StackOverflow中有一个用于编辑问题的选项,作为答案发布附加信息不是一个好习惯。
答案 1 :(得分:0)
编辑:终于找到了“编辑”。做得更漂亮。 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。对不起,我不会说得那么好,所以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*
############################################
谢谢,
韦斯