c++中调用c编写的动态链接库出现undefined reference to `xxx‘的解决方法

1 问题现象

用c语言写了个lib ,编译成了动态链接库,然后建了一个QT项目,想调用自己编写的lib里面的函数,编译的时候发现build OK,但是link的时候error,找不到lib 里面的函数。

[ 20%] Automatic MOC and UIC for target gst_player
[ 20%] Built target gst_player_autogen
[ 40%] Linking CXX executable gst_player
CMakeFiles/gst_player.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x52): undefined reference to `Start_Play(char*)'
main.cpp:(.text+0x89): undefined reference to `Stop_Play()'
collect2: error: ld returned 1 exit status
CMakeFiles/gst_player.dir/build.make:154: recipe for target 'gst_player' failed
make[2]: *** [gst_player] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/gst_player.dir/all' failed
make[1]: *** [CMakeFiles/gst_player.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

lib的名称是mmplayer,lib的头文件里已经声明了这两个接口,QT项目中也引入了这个头文件:

int Start_Play(char *path);
int Stop_Play(void);

QT项目构建方式选择了cmake,cmake中通过link_directories和include_directories直接设置库文件和头文件的地址。

include_directories(${PROJECT_SOURCE_DIR}) 
link_directories(${PROJECT_SOURCE_DIR})
find_library (libpath mmplayer ${PROJECT_SOURCE_DIR})

if (${libpath} STREQUAL "libpath-NOTFOUND")
    message (STATUS "required mmplayer library but not found!")
else()
    message (STATUS "libpath library found in ${libpath}")
endif()

add_executable(gst_player
  main.cpp
  mainwindow.cpp
  mainwindow.h
  mainwindow.ui
)
message(${PROJECT_SOURCE_DIR}/libs/)
target_link_libraries(gst_player PRIVATE Qt5::Widgets mmplayer)

2 问题原因及解决方案

一开始以为是路径设置不对,但是find_library也可以找到这个lib,但是就是链接不到。

zhy@zhy-ThinkPad-E480:~/code/mypc/blog_code/gst_player/qt_gst_player/gst_player$ cmake ./
...
-- libpath library found in /home/zhy/code/mypc/blog_code/gst_player/qt_gst_player/gst_player/libs/libmmplayer.so
-- Configuring done
-- Generating done
-- Build files have been written to: /home/zhy/code/mypc/blog_code/gst_player/qt_gst_player/gst_player

于是用c写了一个程序来调用这个lib,main.c中的内容:

#include <mediaPlayer.h>

int main()
{
    int ret = 0;
    char *filePath = "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_cropped_multilingual.webm";
    
    ret = Start_Play(filePath);
    if (ret != 0)
    {
        return - 1;
    }

    //play 50s
    sleep(50);

    ret = Stop_Play();
    if (ret != 0)
    {
        return - 1;
    }

    return 0;
}

make文件:

cmake_minimum_required(VERSION 3.5)

project(camke_test LANGUAGES C)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include_directories(${PROJECT_SOURCE_DIR}) # 头文件的路径
link_directories(${PROJECT_SOURCE_DIR})
find_library (libpath mmplayer ${PROJECT_SOURCE_DIR})

if (${libpath} STREQUAL "libpath-NOTFOUND")
    message (STATUS "required mmplayer library but not found!")
else()
    message (STATUS "libpath library found in ${libpath}")
endif()

add_executable(camke_test
  main.c
)
message(${PROJECT_SOURCE_DIR}/libs/)
target_link_libraries(camke_test PRIVATE mmplayer)

然后编译,发现link也OK,说明了camke 里的so 链接没有问题。

zhy@zhy-ThinkPad-E480:~/code/mypc/blog_code/gst_player/cmake_test$ make
[ 50%] Building C object CMakeFiles/camke_test.dir/main.c.o
/home/zhy/code/mypc/blog_code/gst_player/cmake_test/main.c: In function ‘main’:
/home/zhy/code/mypc/blog_code/gst_player/cmake_test/main.c:17:5: warning: implicit declaration of function ‘sleep’ [-Wimplicit-function-declaration]
     sleep(50);
     ^~~~~
[100%] Linking C executable camke_test
[100%] Built target camke_test

折腾了一晚上,后来搜索发现是C++调用C存在混编问题,详细原因可自行在网上百度。解决方案很简单,QT中引入用c编写的lib的头文件时用extern "C"来包含。

extern "C"
{
#include <mediaPlayer.h>
}

这样作的作用是告诉编译器,在编译C++的时候被调用的C代码仍然使用C编译选项,然后QT工程就可以顺利的编译通过了。

[ 20%] Automatic MOC and UIC for target gst_player
[ 20%] Built target gst_player_autogen
Scanning dependencies of target gst_player
[ 40%] Building CXX object CMakeFiles/gst_player.dir/main.cpp.o
[ 60%] Linking CXX executable gst_player
[100%] Built target gst_player

3 参考文章

https://blog.csdn.net/weixin_38956024/article/details/112549395

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值