c++ - 来自调用程序的对库类成员的 undefined reference 错误

标签 c++ cross-platform shared-libraries undefined-reference

,2011年4月11日添加了其他问题

尽管我必须能够支持C,但是我正在开发C++中跨平台的共享库DLL / Sos和测试器程序集。这些库将仅作为目标代码提供,但测试器程序将与源代码一起提供,因此我们的客户可以获取示例代码。因此,我正在设计要在运行时加载的库,即使用dlopen()/ LoadLibraryA()进行动态链接。

我在Umbutu 10.04上使用g++ 4.4.3-4,在Vista / 64上使用VC++ 2008(在32位模式下)。

一切似乎在Windows上都可以正常工作(现在)。但是,当我在Linux上编译时,出现一些错误,无法弄清。

测试器和库中有几个用.cpp和.h编码的类。库中的类和除主入口点外的所有其他内容都位于 namespace DISCOVER_NS中。

这是该项目的简要草图:

首先,为了方便起见,我缩短了一些名称,使代码更易读。

discover.cpp

  • 创建一个带有指向它的指针的类对象,该指针称为DiscoverObject类型的MainObject。
  • 具有一个外部“C”函数,该函数将MainObject作为void *返回给调用程序。
  • DiscoverObject有几种方法,可以实例化在单独的cpp和.h中找到的其他类。一种特定的方法名为Hello(),它可以完成您所期望的操作,它会打印“hello”测试消息。.


  • tester.cpp
  • 获取库
  • 的句柄
  • 获取指向返回MainObject的函数的函数指针。
  • 执行函数(指针)并将返回的地址从void *强制转换为DISCOVER_NS::DiscoverObject * aDiscoverObject。
  • 运行aDiscoverObject-> Hello()。


  • 我编译:

    CC = @ g++

    gflags = -g3

    cflags = -fPIC -Wall -pedantic

    lib_linkflags:=-共享-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()的 undefined reference *

    我还从discover.so中得到了一堆其他未定义的引用错误,例如:
    * discover.so:对`Discover_NS::DeviceList::〜DeviceList()的 undefined reference *

    我尝试在SO extern“C”中制作几乎所有内容。没有不同。

    我尝试将如下所示的语句放入discover.cpp中:
    extern void Discover_NS::OtherClass::method(args);
    但这给了我关于“类外声明不是定义”错误的错误。

    我知道看代码会有所帮助,但是我需要时间来整理一些小的东西以便发布。

    谁能提供解决这个困惑的想法?

    谢谢,

    韦斯

    Dmitry的解决方案不是全部解决方案,而是解决方案中的必要元素。在检查我的makefile时,我发现删除了一些无意重复的行,并删除了两个“typos”,其中-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文件的事实。花了一个小时的时间才能删除所有的nit图片,但现在她可以从makefile进行编译了。

    原始问题的新版本:现在,我知道它将通过makefile起作用,如何与Eclipse一起完成makefile的工作?

    谢谢德米特里。

    韦斯

    好吧,我的问题仍然存在。

    我已将代码与Dmitry(@Dmitry)的建议一起编译到位。只是,它们似乎引起了单独的问题。我希望我的库在运行时动态链接到他的主要测试程序。在链接中添加-l Discover -l EdgeIO可以编译所有内容,但它可以实现静态链接。

    仅供引用,未使用的“pi”是这样,因此SO中具有浮点数,因此将在浮点支持下进行编译。如果 call 者曾经想使用浮点数,则为必填。有人有更好的方法强制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
    

    它们应该放在目标文件之后,因为链接器会在命令行遇到它们时加载它们,并搜索 undefined symbol 。

    有关更多信息,请参见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++ - 来自调用程序的对库类成员的 undefined reference 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5556662/

    相关文章:

    c++ - 从 GetLastError() 函数返回的错误代码中获取文本

    android - 我应该为跨平台应用程序使用哪个 BLE Beacon?

    javascript - 如何在 Angular 4 模块中延迟加载库?

    c++ - 尝试使用 dlopen 加载库时 undefined symbol

    c++ - 双脚本数组作为左值

    c++ - 为什么 C 样式转换允许您转换为私有(private)基类?

    c++ - 如何在 C++ 中访问 SQL DB?

    haskell "libraries"

    c++ - 定义调用约定有什么意义?

    linux - 是否可以从非 linux 系统远程调试 linux 代码?