【问题标题】:Error "undefined reference to" to some not-inline methods of a library对库的某些非内联方法的“未定义引用”错误
【发布时间】:2013-03-12 11:28:09
【问题描述】:

解决that 问题后,我有一个新问题:

情况:我有一个使用 C++ 编写的库的 C 项目。从 C 中只有对函数的调用,但是这些函数的实现使用类。

详情:

库编译没有错误,但编译C项目返回以下错误:

...
Start.cpp:(.text+0x860): undefined reference to `InitialCondition::Load(std::string, bool)'
Start.cpp:(.text+0x227b): undefined reference to `InitialCondition::SetMachIC(double)'
...

一般:

<calling library implementation>:(...): undefined reference to <a class>::<a method>

这通常表明缺少该库,但在这种情况下,我可以使用该库的大部分功能——只有在实现中使用了一些类时它才会失败。

这是一个例子:

在 C++ 库中:

开始.h

...

#ifdef __cplusplus
extern "C"
{
#endif

    void start();
    ...
#ifdef __cplusplus
}
#endif

Start.cpp

#include "Start.h"
#include "InitialCondition"

InitialCondition* initCond;

void start()
{
    // initCond is set somewhere here
    ...
    initCond->SetMachIC(1.0);     // (A) has no reference
    initCond->SetAlphaDegIC(2.0); // (B) has a reference
}

InitCondition.h

// includes etc.

class InitialCondition : public ABaseClass
{
public:

    void SetMachIC(double mach);

    void SetAlphaDegIC(double a)
    {
        // inline implementation
    }   
};

从 C 调用:

#include "Start.h"

void example()
{
    start();
}

由于该库是使用cmake 构建的,因此这里是关联CMakeLists.txt 的部分:

set(INITIALISATION_SRC InitialCondition.cpp)
set(INITIALISATION_HDR InitialCondition.h)

add_library(Init ${INITIALISATION_HDR} ${INITIALISATION_SRC})
set_target_properties (Init PROPERTIES
                            VERSION "${LIBRARY_VERSION}")

if(BUILD_SHARED_LIBS)
  set_target_properties (Init PROPERTIES
                              SOVERSION ${LIBRARY_SOVERSION}
                              FRAMEWORK ON)
endif()

install(TARGETS Init LIBRARY DESTINATION lib
                     ARCHIVE DESTINATION lib
                     RUNTIME DESTINATION lib
                     # For Mac
                     FRAMEWORK DESTINATION "/Library/Frameworks")
install(FILES ${INITIALISATION_HDR} DESTINATION include/Project/initialization)

(有一长串 .cpp.h 文件,我已经缩短了一点)

注意:顺便说一句。还是有一些非行方法调用没有这样的错误。

注意:这些文件位于子目录中。它使用add_subdirectory(initialization)添加

注意:nm编译库列表包含:InitialCondition9SetMachICEd

为什么从 C 调用时没有引用这些方法——即使库已链接并且方法的实现可用?


编辑:

以下是用于 C 的命令:

编译:

gcc -I"<include dir>" -O0 -g -Wall -c -fmessage-length=0 -MMD -MP -MF"src/Test.d" -MT"src/Test.d" -o "src/Test.o" "../src/Test.c"

链接:

gcc -L"<searchpath>" -shared -o "libTest.dll"  ./src/Test.o   -l<library name> -lstdc++

Test.d 包含#include 中包含的所有文件的列表

【问题讨论】:

  • 你用哪个命令编译C代码?
  • 是否有可能生成一个最小的、可编译的测试用例,其中包含:1. 仅重现此问题的基本要素和 2. 无需猜测或填充即可重现此问题的足够代码(和命令)在空白处?这样我们就可以准确地判断您做错了什么,并更好地为您指明正确的方向。
  • 您是否尝试过将 c++ 应用程序与库链接?我猜有一些内部未定义的引用在编译库时没有显示出来。
  • 第一个库上的nm 是否显示TU 或其他用于该功能的内容?
  • 如果您的库也无法与 c++ 链接,那么您的库就有问题。尝试让它与一个最小的 c++ 示例一起工作,那么它也应该与 C 一起工作。

标签: c++ linker cmake mingw


【解决方案1】:

C++ 会破坏名称,而 C 不会。 C++ 函数用

之类的东西装饰

__someletters_function_name_

要获得 C 样式名称修饰,您应该使用 extern "C" { ... },但老实说,我不确定它如何与类或 C++ 项目(包括您的库)交互。

【讨论】:

  • 在我的代码中使用了它,但没有将它插入到我的示例中。从 C 调用的所有函数都在这样的 extern "C" 块中(在标题中),但是这不起作用。
【解决方案2】:

问题似乎是由损坏的 cmake 列表引起的。经过几次更改,我现在可以编译两者。然而这对我来说真的很奇怪,因为所有文件都存在于 cmakelists 中。

【讨论】:

    猜你喜欢
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    • 2011-12-22
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    相关资源
    最近更新 更多