【问题标题】:CMake JNI errorCMake JNI 错误
【发布时间】:2013-09-25 00:35:29
【问题描述】:

我编写了一个绑定 C++ 类,它从 C++ 调用 java。我正在尝试使用 CMake 编译绑定类(因为将使用绑定类的工具使用 CMake)。

但是我收到以下错误:

CMakeFiles/JNIWrapper.dir/JNIWrapper.cpp.o: In function `createVM(JavaVM_**)':
JNIWrapper.cpp:(.text+0x52): undefined reference to `JNI_CreateJavaVM'
collect2: ld returned 1 exit status
make[2]: *** [JNIWrapper] Error 1
make[1]: *** [CMakeFiles/JNIWrapper.dir/all] Error 2
make: *** [all] Error 2

这是我的 CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.6)

project(AProject)

FIND_PACKAGE(JNI REQUIRED)

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/lib/jvm/java-6-openjdk-amd64/include -I/usr/lib/jvm/java-6-openjdk-amd64/include/linux -L/usr/lib/jvm/java-6-openjdk-amd64/jre/lib/amd64/server")

SET(CMAKE_EXE_LINKER_FLAGS "-ljvm")

# add the binary tree directory to the search path for include files
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${JNI_INCLUDE_DIRS})

# add the executable
add_executable (JNIWrapper JNIWrapper.cpp)

欢迎提出任何建议。

PS:我尝试使用传统方式和编写makefile来编译它。我按照那个例子写了上面的 CMakeLists.txt 脚本。

【问题讨论】:

    标签: java-native-interface cmake


    【解决方案1】:

    以下CMakeLists.txt 概述了使用 CMake 构建示例 JNI 项目所需的步骤:

    cmake_minimum_required (VERSION 3.0)
    
    find_package(Java REQUIRED)
    find_package(JNI REQUIRED)
    include(UseJava)
    
    enable_testing()
    project (JNIFoo)
    
    # compile JNIFoo.java to class file
    set(CMAKE_JAVA_COMPILE_FLAGS "-source" "1.6" "-target" "1.6")
    add_jar(JNIFoo JNIFoo.java)
    get_target_property(_jarFile JNIFoo JAR_FILE)
    get_target_property(_classDir JNIFoo CLASSDIR)
    
    # generate JNIFoo.h stub
    set (_stubDir "${CMAKE_CURRENT_BINARY_DIR}")
    add_custom_command(
        OUTPUT JNIFoo.h
        COMMAND ${Java_JAVAH_EXECUTABLE} -verbose
            -classpath ${_classDir}
            -d ${_stubDir}
            -jni JNIFoo
        DEPENDS JNIFoo
        )
    
    # generate libfoo.jnilib
    include_directories(${JNI_INCLUDE_DIRS} ${_classDir} ${_stubDir})
    add_library(foo MODULE foo.c JNIFoo.h)
    set_target_properties(foo PROPERTIES SUFFIX ".jnilib")
    target_link_libraries(foo ${JNI_LIBRARIES})
    
    # add test to run JNIFoo
    add_test(NAME TestJNIFoo
        COMMAND ${Java_JAVA_EXECUTABLE}
        -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}
        -cp ${_jarFile} JNIFoo)
    

    文件JNIFoo.java 包含一个Java 类,该类将foo.c 中的函数声明为本机方法nativeFoofoo.c 包含方法 nativeFoo 的 C 实现。

    CMake 函数 add_jar 将 Java 类编译为 jar 文件,并作为副作用创建一个类文件,该文件需要作为输入传递给 javah C 存根文件生成器可执行文件。使用自定义命令调用javah 以生成存根标头JNIFoo.h 作为输出文件。

    由于 Java 在运行时使用 System.loadLibrary 加载 JNI 库,因此必须使用 CMake 命令 add_library 将 JNI 库生成为 MODULE 库。将JNIFoo.h 添加为源文件可确保在编译库之前创建JNIFoo.h。编译后的 JNI 库需要与变量 JNI_LIBRARIES 中包含的 JDK JNI 库链接。 JNI_INCLUDE_DIRS 包含要使用的 JNI 包含目录。

    最后,添加了一个测试以使用 JVM 运行 JNIFoo 类。系统属性java.library.path必须设置为包含生成的JNI库libfoo.jnilib的目录。

    【讨论】:

    • 这很有用,但没有找到 $JAVA_HOME/include 文件夹而不做: include_directories(${JAVA_INCLUDE_PATH} ${_classDir} ${_stubDir} $ENV{JAVA_HOME}/include/linux $ ENV{JAVA_HOME}/include/)
    • 对于 Linux,您可能需要使用 ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2}。第二个包含路径是 jni_md.h,它包含在 Linux 中的 jni.h 中
    • 变量JNI_INCLUDE_DIRS 包含用于JNI 编译的所有必要目录。我已经更新了答案。
    猜你喜欢
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多