c重构为c++踩坑记录

CMakeList中的Project(xxx)

  • 可以只起名,不限定语言,这样的话在add_library中添加的所有路径/文件都会被cmake解析到,例如:
project(aaa)
add_library(${SO_NAME} SHARED ${SRC}
        src/main.cpp
		src/test.c)
  • 如果在project中限定语言,就表示只接受这几种类型的语言,其他语言的文件添加了也不会被cmake加载(实验:去掉括号中的C,并且在test.c中随便写点错误,并不会被编译器解析到)
    project(aaa C CXX)

  • 头文件添加进来也没用,甚至也不会添加进include_path搜索

关键字

error: expected initializer before 'extern' __BEGIN_DECLS

image

  • 多半是因为头文件的声明后面没加分号

编写gtest(so库连接到bin)踩坑

情况是:我的工程需要从c-->c++ 但是c++工程仍然需要调用一些c库的接口,这些c接口并没有在声明的时候加extern c, 于是我发现我的工程编译出来的so,如果被其他bin链接,会报错提示找不到符号

image

  • 根因分析:c/c++工程的cmakelist,至少需要包含:
link_directories{
      /pathA
	  /pathB
}
add_library(myProject SHARED main.cpp)

target_link_libraries(myProject libxxx.so yyy zzz)
  • 其中 add_library就是编译为so,即libmyProject.so,add_executable是编译为bin
  • 编译为so/bin的区别在于,编译为so时,只需确保连接的所有其他so库在link_directories中即可,但是编译为bin,还会校验符号表
  • 符号表的查看方式: nm xxx/build/path/libmyProject.so (具体路径取决于build.sh 或 install命令指定)

我把我直接编译出来的so(没有原则性问题不会报错)查看一下符号表

nm ./build/libmyProject.so | grep func

发现显示为 T _Z20funcPKiPKdii
image

只要带有_Z修饰的就是表示被C++名称修饰过了,这就是问题所在!!

  • 因为被名称修饰过,所以我的其余c++文件想要调用它就会在so符号表中找不到他,因为我调用的c库没有使用extern "C" 修饰它的声明。导致我调用的这个c接口在它所在的so中符号表为不带_Z的,但是因为我名称修饰他了,就相当于符号表变了,就找不到了!!!!

解决方案就是,因为我不能随意更改别人的c头文件,所以只能在所有引用到该c接口的位置前后extern C 并且在用到该c接口的我的对外接口声明extern C 问题完美解决!感谢公司大佬协助排查QAQ

posted @ 2024-11-18 18:09  __Zed  阅读(38)  评论(0)    收藏  举报