【问题标题】:Unexpected undefined reference意外的未定义引用
【发布时间】:2012-07-20 13:39:07
【问题描述】:

我收到一个未定义的引用错误,不知道原因。

所以我有 2 个创建静态库的文件:keyboard_input.c、keyboard_input.h

这是 .h 文件的内容:

#ifndef __MOD_KBINPUT__
#define __MOD_KBINPUT__

int kbInit();
int kbWait();

int kbTest();

#endif

CMakeLists.txt 文件如下所示:

FILE(
GLOB_RECURSE
sources
*.c
)
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/include/utils/kbreader")
ADD_LIBRARY(keyboardReader ${sources})

编译这个库会给出一些警告:

src/utils/kbreader/keyboard_input.c: In function ‘kbInit’:
src/utils/kbreader/keyboard_input.c:13:14: warning: assignment from incompatible pointer type [enabled by default]
src/utils/kbreader/keyboard_input.c: In function ‘kbWait’:
src/utils/kbreader/keyboard_input.c:21:55: warning: passing argument 4 of ‘fread’ from  incompatible pointer type [enabled by default]
/usr/include/stdio.h:708:15: note: expected ‘struct FILE * __restrict__’ but argument is of type ‘struct FILE *’

现在,对于我的主要可执行文件 (main.cpp):

#include <keyboard_input.h>
int main()
{
  kbTest();
  return 0;
}

由以下 CMakeLists.txt 文件处理:

include_directories("${PROJECT_SOURCE_DIR}/include/utils/kbreader")

file(
    GLOB_RECURSE
    srcs
    *.cpp
)

add_executable(
    PEM
    ${srcs}
)
target_link_libraries(PEM keyboardReader)

最终得到那个错误:

CMakeFiles/PEM.dir/main.cpp.o: In function `main':
main.cpp:(.text+0xb): undefined reference to `kbTest()'
collect2: ld returned 1 exit status
make[2]: *** [src/PEM/main2/PEM] Error 1
make[1]: *** [src/PEM/main2/CMakeFiles/PEM.dir/all] Error 2

libkeyboardReader.a 被创建,kbTest() 函数除了没有做任何事情

{return 0; }

如果我在头文件中设置 kbTest() 的定义,它就可以工作。

但是当我输入时,有些东西我没有得到:make keyboardReader 这里是输出:

[ 73%] Building C object src/utils/kbreader/CMakeFiles/KeyboardReader.dir/keyboard_input.c.o
[Warning explained above]
Linking C static library ../../../lib/libKeyboardReader.a

有什么问题吗? note 错误消息是否使我的 lib 省略了 keyboard_input.c 文件?

【问题讨论】:

    标签: c++ c cmake static-libraries


    【解决方案1】:

    您正在混合 C 和 C++ 文件。为了让它工作,你只需要告诉 C++ 编译器它正在调用一个 C 函数,方法是像这样改变头文件:

    #ifndef MOD_KBINPUT
    #define MOD_KBINPUT
    /* note I also fixed the macro so you aren't using a system-reserved name */
    
    #if __cplusplus
    /* this is the important part */
    extern "C" {
    #endif
    
    int kbInit();
    int kbWait();
    
    int kbTest();
    
    #if __cplusplus
    }
    #endif
    
    #endif
    

    否则,C++ 编译器会假定该函数将被赋予一个 C++ 内部名称(它对签名中的所有类型信息进行编码,这是让链接器区分重载函数的原因),然后链接器找不到它。

    【讨论】:

    • 图标和按钮未显示,我不确定它是否已将您的答案标记为已接受。但谢谢。终于知道了 extern {} 部分的用途,我感到如释重负。
    猜你喜欢
    • 1970-01-01
    • 2023-01-22
    • 2015-06-02
    • 2021-03-07
    相关资源
    最近更新 更多