如何将C++项目链接到pybind11模块?CMake编译错误解决
pybind11绑定C++程序的CMake链接问题解决
问题场景
现有一个名为my_exec的C++程序,其中包含简单的加法函数:
int add(int i, int j) { return i+j; }
为其编写了pybind11绑定代码:
#include <pybind11/pybind11.h> #include "lib.h" // add函数的声明在此,实现位于lib.cpp PYBIND11_MODULE(cpp, m) { m.doc() = "first python binding."; m.def("add", &add, "A function that adds 2 numbers"); m.def("mul", &mul, "A function that multiply 2 numbers"); }
使用CMake构建pybind模块时,出现链接错误:
Cannot specify link libraries for target "pybind" which is not built by this project.
主CMakeLists.txt配置
# 仅支持cmake版本 >= 3.5.1 cmake_minimum_required(VERSION 3.5.1) if (CMAKE_BUILD_TYPE MATCHES Debug) message("Cmake in debug mode.") else () message("Cmake in release mode.") endif (CMAKE_BUILD_TYPE MATCHES Debug) # 项目名称 project(my_exec) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 生成LSP所需的compile_commands.json set(CMAKE_EXPORT_COMPILE_COMMANDS 1) # 头文件包含目录 include_directories( src /media/romain/Donnees/Programmation/C++/frameworks /media/romain/Donnees/Programmation/C++/frameworks/files /media/romain/Donnees/Programmation/C++/libs/json /media/romain/Donnees/Programmation/C++/libs/boost-install/include ) # 链接库目录 link_directories(build/libs) # 收集所有需要编译的.cpp文件 file(GLOB SOURCES src/*.cpp /media/romain/Donnees/Programmation/C++/frameworks/debug.cpp /media/romain/Donnees/Programmation/C++/frameworks/str.cpp ) # 根据构建模式设置编译选项 if (CMAKE_BUILD_TYPE MATCHES Debug) add_compile_definitions(mydebug) add_compile_options(-Og) else() add_compile_options(-O3) endif(CMAKE_BUILD_TYPE MATCHES Debug) # 编译生成可执行文件 add_executable(${PROJECT_NAME} ${SOURCES}) # 添加pybind子目录 add_subdirectory(pybind) # 尝试让可执行文件可被其他库链接 set_target_properties(${PROJECT_NAME} PROPERTIES ENABLE_EXPORTS on) # 链接依赖库 target_link_libraries(${PROJECT_NAME} pthread stdc++fs )
pybind子目录CMakeLists.txt配置
cmake_minimum_required(VERSION 3.5) project(pybind) include_directories(/media/romain/Donnees/Programmation/C++/libs/pybind11/include) add_subdirectory(/media/romain/Donnees/Programmation/C++/libs/pybind11 ./pybind11_build) # 生成pybind模块 pybind11_add_module(cpp ../src/pybind/cpp.cpp) # 尝试链接my_exec可执行文件 target_link_libraries(${PROJECT_NAME} PRIVATE my_exec)
解决方案
核心问题:Python扩展模块无法直接链接可执行文件,必须将my_exec编译为共享库。
修改主CMakeLists.txt中的编译目标类型,将:
add_executable(${PROJECT_NAME} ${SOURCES})
替换为:
add_library(my_exec SHARED ${SOURCES})
原因:可执行文件默认不会导出完整符号表(即便设置ENABLE_EXPORTS也无法替代共享库的设计定位),而共享库是专门为被其他程序/模块链接调用而设计的,能确保pybind模块正确找到add等函数的实现。
内容的提问来源于stack exchange,提问作者Romain
相关产品推荐
相关产品推荐

