首页 > 解决方案 > 如何为 JNI 和 C++ 代码创建适当的 CMakeLists.txt?

问题描述

我的目标

我正在尝试构建一个简单项目的 java 和 C++ 接口来检查数字是偶数还是奇数。java 代码应该生成 C++ 头文件,然后我将从 C++ 内部为 java 函数编写函数定义并构建一个库 (.so) 文件。稍后,我将运行 java 代码来打印 C++ 生成的输出。为此,我编写了一个简单的 java 类,然后使用本教程编写了 C++ 成员函数。

我的代码非常简单。我在下面复制了它:

奇数校验.java

public class OddNumCheck {
   static {
      System.loadLibrary("odd_num"); // libodd_num.so (MacOS/ Unix)
   }
 
   // Declare a native method odd_test() that receives an int and prints to the console whether it is odd or even
   private native String odd_test(int num);
 
   // Test Driver
   public static void main(String args[]) {
      System.out.println("In the Java program the given input number is " + new OddNumCheck().odd_test(3));
   }
}

奇数校验.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class OddNumCheck */

#ifndef _Included_OddNumCheck
#define _Included_OddNumCheck
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     OddNumCheck
 * Method:    odd_test
 * Signature: (I)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_OddNumCheck_odd_1test
  (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif

奇数校验.cpp

#include <jni.h>
#include "OddNumCheck.h"

JNIEXPORT jstring

/*!
 * @brief The odd_test function is a JNI function which takes an input integer from a java function odd_test() inside
 * java a class OddNumCheck, and returns a string saying whether the passed integer is Odd or Even
 * @param num a Java integer of type jint
 * @return a java string with one of the two possibilities "Odd" or "Even"
 * */
JNICALL Java_OddNumCheck_odd_1test(JNIEnv *env, jobject obj, jint num) {
    jstring num_type;
    if (num % 2 == 0) {
        num_type = env->NewStringUTF("Even");
    } else {
        num_type = env->NewStringUTF("Odd");
    }
    return num_type;
}

这是我的项目结构:

OddNumCheck
 |_ CMakeLists.txt
 |_ OddNumCheck.cpp
 |_ OddNumCheck.h
 |_ OddNumCheck.java

我能够编译代码并生成一个 lib (.so) 文件,然后使用非 cmake 方法(在终端中键入手动编译指令)将输出打印到控制台。现在我正在尝试将东西打包成一个漂亮而干净的 CMakeLists.txt 文件,这将使我能够一次轻松地完成所有事情。

因此,我遵循了这个 CMakeLists.txt文件,该文件似乎与我正在寻找的内容非常相关,并按照其中的说明进行操作。

以下是我的CMakeLists.txt

cmake_minimum_required (VERSION 3.0)
project (OddNumCheck)

find_package(Java REQUIRED)
find_package(JNI REQUIRED)
if (JNI_FOUND)
    message (STATUS "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}")
    message (STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}")
endif()
include(UseJava)

enable_testing()

# compile JNIFoo.java to class file
set(CMAKE_JAVA_COMPILE_FLAGS "-source" "1.6" "-target" "1.6")
add_jar(OddNumCheck OddNumCheck.java)
get_target_property(_jarFile OddNumCheck JAR_FILE)
get_target_property(_classDir OddNumCheck CLASSDIR)

# generate JNIFoo.h stub
set (_stubDir "${CMAKE_CURRENT_BINARY_DIR}")
add_custom_command(
        OUTPUT OddNumCheck.h
        COMMAND ${Java_JAVAH_EXECUTABLE} -verbose
        -classpath ${_classDir}
        -d ${_stubDir}
        -jni OddNumCheck
        DEPENDS OddNumCheck
)

# generate libfoo.jnilib
include_directories(${JNI_INCLUDE_DIRS} ${_classDir} ${_stubDir})
add_library(libodd_num MODULE OddNumCheck.cpp OddNumCheck.h)
set_target_properties(libodd_num PROPERTIES SUFFIX ".so")
target_link_libraries(libodd_num ${JNI_LIBRARIES})

# add test to run JNIFoo
add_test(NAME TestOddNumCheck
        COMMAND ${Java_JAVA_EXECUTABLE}
        -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}
        -cp ${_jarFile} OddNumCheck)

不幸的是,我的 CMake 无法编译。我收到以下错误(来自 CLion IDE):

====================[ Build | all | Debug ]=====================================
/usr/local/bin/cmake --build /mnt/f/sandbox/OddNumCheck/cmake-build-debug --target all -- -j 6
[ 50%] Built target OddNumCheck
[ 66%] Generating OddNumCheck.h
make[2]: Java_JAVAH_EXECUTABLE-NOTFOUND: Command not found
CMakeFiles/libodd_num.dir/build.make:61: recipe for target 'OddNumCheck.h' failed
make[2]: *** [OddNumCheck.h] Error 127
CMakeFiles/Makefile2:104: recipe for target 'CMakeFiles/libodd_num.dir/all' failed
make[1]: *** [CMakeFiles/libodd_num.dir/all] Error 2
Makefile:94: recipe for target 'all' failed
make: *** [all] Error 2

更新

我也试过这个CMakeLists.txt文件。这也没有帮助。

标签: javac++cmakecompilationjava-native-interface

解决方案


推荐阅读