CMake JNI错误 [英] CMake JNI error

查看:104
本文介绍了CMake JNI错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



但是我收到以下错误:

  CMakeFiles / JNIWrapper。 dir / JNIWrapper.cpp.o:在函数`createVM(JavaVM _ **)'中:
JNIWrapper.cpp :(。text + 0x52):对'JNI_CreateJavaVM'的未定义引用
collect2:ld返回1退出状态
make [2]:*** [JNIWrapper]错误1
make [1]:*** [CMakeFiles / JNIWrapper.dir / all]错误2
make:*** [all]错误2

这是我的CMakeLists.txt:

  cmake_minimum_required(版本2.8.6)

项目(AProject)

FIND_PACKAGE(需要JNI)

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)

#将二叉树目录添加到包含文件
include_directories($ {CMAKE_CURRENT_SOURCE_DIR})
include_di的搜索路径中rectories($ {JNI_INCLUDE_DIRS})

#添加可执行文件
add_executable(JNIWrapper JNIWrapper.cpp)

任何建议都值得赞赏。



PS:我尝试使用传统方式并通过编写makefile对其进行编译。我遵循了该示例,并在上面编写了CMakeLists.txt脚本。

解决方案

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

  cmake_minimum_required(VERSION 3.0)

find_package(需要Java)
find_package(需要JNI)
include(UseJava)

enable_testing()
项目(JNIFoo)

#将JNIFoo.java编译为类文件
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)

#生成JNIFoo.h存根
set(_stubDir $ {CMAKE_CURRENT_BINARY_DIR add()}

输出JNIFoo.h
命令$ {Java_JAVAH_EXECUTABLE}-详细
-classpath $ {_ classDir}
-d $ {_ stubDir}
-jni JNIFoo
依赖JNIFoo


#生成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})

#添加测试以运行JNIFoo
add_test(NAME TestJNIFoo
COMMAND $ {Java_JAVA_EXECUTABLE}
-Djava.library.path = $ {CMAKE_CURRENT_BINARY_DIR}
-cp $ {_ jarFile} JNIFoo)

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



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



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



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

I've written a binding C++ class that calls java from C++. I am trying to compile the binding class using CMake (because the tool that will use the binding class uses CMake).

However I receive the following error:

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

Here is my 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)

Any suggestion is appreciated.

PS: I have tried to compile it using the traditional way and by writing a makefile. I followed that example and wrote the CMakeLists.txt script above.

解决方案

The following CMakeLists.txt sketches the steps required to build a sample JNI project with CMake:

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)

The file JNIFoo.java contains a Java class that declares a function in foo.c as a native method nativeFoo. foo.c contains the C implementation of the method nativeFoo.

The CMake function add_jar compiles the Java class to a jar file and, as a side effect, creates a class file which needs to be passed as an input to the javah C stub file generator executable. A custom command is used to invoke javah to generate the stub header JNIFoo.h as an output file.

Because Java uses System.loadLibrary to load JNI libraries at runtime, the JNI library must be generated as a MODULE library using the CMake command add_library. Adding JNIFoo.h as a source file ensures that JNIFoo.h will be created before the library is compiled. The compiled JNI library needs to be linked with the JDK JNI libraries contained in the variable JNI_LIBRARIES. JNI_INCLUDE_DIRS contains the the JNI include dirs to use.

Finally, a test is added to run the class JNIFoo with the JVM. The system property java.library.path must be set to the directory containing the generated JNI library libfoo.jnilib.

这篇关于CMake JNI错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆