java和c语言的混合开发
在Java 21中使用JNI技术和CMake来实现Java和C语言的混合开发。
将SQLite和哈希等低级操作与Java代码集成在一起。
有关代码: https://git.wqyblog.cn/wuqiyang312/wqyTools
项目目标是创建一个共享库(wqyToolsJni
),并提供Java接口来调用C++的SQLite和哈希功能。
以下是详细的配置步骤,包括Java和C/C++代码的开发、JNI头文件生成,以及使用CMake来构建共享库。
项目结构
首先,创建以下项目结构:
project-root/
├── CMakeLists.txt # CMake构建文件
├── src/
│ ├── main/
│ │ └── java/cn/wqyblog/wqytools/jni/Jni.java # Java代码
├── native/
│ ├── library.cpp # 自定义C++库代码
│ ├── sqlite3Library.cpp # SQLite相关的C++封装
│ ├── hashLibrary.cpp # 哈希相关的C++封装
│ ├── sqlite/
│ │ └── sqlite3.c # SQLite源码
└── build/ # CMake构建目录
1: 编写Java代码
在src/main/java/cn/wqyblog/wqytools/jni/Jni.java
中,编写如下Java类,用于定义native方法:
package cn.wqyblog.wqytools.jni;
public class Jni {
static {
System.loadLibrary("wqyToolsJni");
}
// ==== sqlite ====
public static native boolean sqliteOpen(String path);
public static native boolean sqliteClose();
public static native boolean sqliteCreateTable();
public static native String sqliteGetConfig(String key);
public static native boolean sqliteSetConfig(String key, String value);
public static native boolean sqliteAddConfig(String key, String value);
public static native boolean sqliteDeleteConfig(String key);
// ==== hash ====
public static native String calcFileHash(String filename, String algorithm);
public static native String calcStringHash(String str, String algorithm);
}
2: 编译Java文件并生成JNI头文件
在项目根目录下运行以下命令来编译Java代码并生成头文件:
javac -h native/ src/main/java/cn/wqyblog/wqytools/jni/Jni.java
这将生成一个cn_wqyblog_wqytools_jni_Jni.h
文件,包含了Jni
类中定义的所有native方法的声明。
3: 编写C/C++代码
根据生成的cn_wqyblog_wqytools_jni_Jni.h
,在native/
目录下编写C++代码,以下为示例。
library.cpp
实现sqliteOpen
、sqliteClose
等SQLite相关方法:
#include "cn_wqyblog_wqytools_jni_Jni.h"
#include <sqlite3.h>
// SQLite相关的C++代码实现
JNIEXPORT jboolean JNICALL Java_cn_wqyblog_wqytools_jni_Jni_sqliteOpen(JNIEnv* env, jobject obj, jstring path) {
// SQLite打开数据库代码
}
JNIEXPORT jboolean JNICALL Java_cn_wqyblog_wqytools_jni_Jni_sqliteClose(JNIEnv* env, jobject obj) {
// SQLite关闭数据库代码
}
// 其他JNI实现代码...
hashLibrary.cpp
实现calcFileHash
和calcStringHash
等哈希计算方法:
#include "cn_wqyblog_wqytools_jni_Jni.h"
#include <openssl/sha.h>
#include <string>
// 使用OpenSSL进行文件哈希计算
JNIEXPORT jstring JNICALL Java_cn_wqyblog_wqytools_jni_Jni_calcFileHash(JNIEnv* env, jobject obj, jstring filename, jstring algorithm) {
// 文件哈希计算代码
}
4: 编写CMakeLists.txt
在项目根目录下编写CMakeLists.txt
:
cmake_minimum_required(VERSION 3.28)
project(wqyToolsJni)
set(CMAKE_CXX_STANDARD 17)
# 找到 OpenSSL
find_package(OpenSSL REQUIRED)
add_library(wqyToolsJni SHARED
native/sqlite/sqlite3.c
native/library.cpp
native/sqlite3Library.cpp
native/hashLibrary.cpp)
# 包含 OpenSSL 头文件和Java头文件
find_package(Java REQUIRED)
include_directories(${Java_INCLUDE_DIRS})
include_directories(native)
target_include_directories(wqyToolsJni PRIVATE ${OPENSSL_INCLUDE_DIR})
# 链接 OpenSSL 库
target_link_libraries(wqyToolsJni PRIVATE OpenSSL::SSL OpenSSL::Crypto)
Step 5: 使用CMake构建共享库
进入build/
目录,生成并编译共享库:
mkdir build && cd build
cmake ..
make
生成的libwqyToolsJni.so
共享库将放在build/
目录中。
Step 6: 运行Java测试
在Java代码中设置动态库的加载路径,然后运行Jni
类中的测试代码:
public static void main(String[] args) {
System.load("/path/to/libwqyToolsJni.so"); // 手动加载路径
boolean success = Jni.sqliteOpen("test.db");
System.out.println("SQLite open success: " + success);
}
使用以下命令运行测试代码:
java -cp src/main/java cn.wqyblog.wqytools.jni.Jni