CMakeLists编写:如何通过JNI/JVM实现Python与Java的混合调用
解决方案
一、JNI 依赖配置修复
find_package(JNI) 读取路径的优先级是:系统环境变量 > 缓存变量 > CMakeLists 本地变量,直接在CMakeLists中写set(JAVA_HOME)不生效是因为执行顺序不对,或没有写入缓存。正确配置步骤:
- 必须在
find_package(JNI)之前声明JAVA_HOME,同时写入缓存覆盖系统值:
# 按需修改为你的JDK路径,用正斜杠避免转义问题 set(JAVA_HOME "C:/Program Files/Java/jdk-15.0.1" CACHE PATH "JDK installation path" FORCE) # 显式指定JNI组件路径,避免自动查找失败 set(JAVA_AWT_INCLUDE_PATH "${JAVA_HOME}/include" CACHE PATH "" FORCE) set(JAVA_INCLUDE_PATH "${JAVA_HOME}/include" CACHE PATH "" FORCE) set(JAVA_INCLUDE_PATH2 "${JAVA_HOME}/include/win32" CACHE PATH "" FORCE) set(JAVA_AWT_LIBRARY "${JAVA_HOME}/lib/jawt.lib" CACHE FILEPATH "" FORCE) set(JAVA_JVM_LIBRARY "${JAVA_HOME}/lib/server/jvm.lib" CACHE FILEPATH "" FORCE) # 此时再执行find_package就不会报错了 find_package(JNI REQUIRED)
- 注意JDK架构要和Visual Studio编译目标架构一致:32位编译选32位JDK,64位编译选64位JDK。
二、Python 依赖配置修复
旧版find_package(PythonLibs)已经被废弃,兼容性差容易查找失败,推荐用新版Python查找模块,配置步骤:
- 同样在
find_package之前指定要使用的Python根路径,写入缓存:
# 按需修改为你的Python安装路径 set(Python_ROOT_DIR "C:/Users/xxx/AppData/Local/Programs/Python/Python39" CACHE PATH "Python installation path" FORCE) # 查找Python解释器和开发组件,可指定版本号如Python 3.9 REQUIRED find_package(Python REQUIRED COMPONENTS Interpreter Development) # 如果使用pybind11,直接调用pybind11的查找模块,会自动关联对应Python依赖 find_package(pybind11 REQUIRED)
- 如果项目没有提前安装pybind11到系统路径,可以把pybind11源码作为子模块放到项目目录下,用
add_subdirectory(third_party/pybind11)替代find_package(pybind11)即可。
三、关于pkg_check_modules的说明
pkg-config依赖对应库的.pc配置文件才能正常工作,Windows环境下默认没有Python、JNI对应的.pc文件,所以不要用pkg_check_modules配置这两类依赖,直接用上述CMake原生方案即可。
完整示例CMakeLists.txt
cmake_minimum_required(VERSION 3.18) project(jni_pybind_demo) # 配置JNI依赖 set(JAVA_HOME "C:/Program Files/Java/jdk-15.0.1" CACHE PATH "JDK installation path" FORCE) set(JAVA_AWT_INCLUDE_PATH "${JAVA_HOME}/include" CACHE PATH "" FORCE) set(JAVA_INCLUDE_PATH "${JAVA_HOME}/include" CACHE PATH "" FORCE) set(JAVA_INCLUDE_PATH2 "${JAVA_HOME}/include/win32" CACHE PATH "" FORCE) set(JAVA_AWT_LIBRARY "${JAVA_HOME}/lib/jawt.lib" CACHE FILEPATH "" FORCE) set(JAVA_JVM_LIBRARY "${JAVA_HOME}/lib/server/jvm.lib" CACHE FILEPATH "" FORCE) find_package(JNI REQUIRED) # 配置Python + pybind11依赖 set(Python_ROOT_DIR "C:/Users/xxx/AppData/Local/Programs/Python/Python39" CACHE PATH "Python installation path" FORCE) find_package(Python REQUIRED COMPONENTS Interpreter Development) add_subdirectory(third_party/pybind11) # 或find_package(pybind11 REQUIRED) # 编译目标 add_library(${PROJECT_NAME} SHARED your_source_code.cpp ) # 关联头文件和依赖库 target_include_directories(${PROJECT_NAME} PRIVATE ${JNI_INCLUDE_DIRS} ${Python_INCLUDE_DIRS} ) target_link_libraries(${PROJECT_NAME} PRIVATE ${JNI_LIBRARIES} Python::Module pybind11::pybind11 )
内容的提问来源于stack exchange,提问作者Martin Perry
相关产品推荐
相关产品推荐

