当前位置: 首页 > news >正文

搭建网站工具抚州公司做网站

搭建网站工具,抚州公司做网站,wordpress首页调用所有分类,承德网站建设作用Java 调用 C 动态库(DLL)完整实践:无图像无实体处理场景   这里主要介绍如何通过 JNI(Java Native Interface)在 Java 中调用一个用 C 编写的校色算法库。不涉及图像和 java 实体处理。环境如下: 系统&a…

  Java 调用 C++ 动态库(DLL)完整实践:无图像无实体处理场景
  这里主要介绍如何通过 JNI(Java Native Interface)在 Java 中调用一个用 C++ 编写的校色算法库。不涉及图像和 java 实体处理。环境如下:

  • 系统:Windows 10
  • JDK:1.8
  • IDE:Visual Studio 2022
  • Java 构建工具:Maven
  • 目标平台:x64

一、整体目标

  Java 端通过 JNI 调用算法提供的动态库,实现图像缺色偏色检测功能。为了方便,我把所有的依赖库都放在了 jdk 的 bin 目录,这样我在调用的时候只需要导入我的自己生成的 jni 库就可以,如果需要频繁切换 jdk,那建议自己配置 java.library.path 或将依赖库放到独立目录中 ,处理好动态库的依赖关系即可。


二、准备工作

1. C++ 头文件(API 定义)

  这是算法的头文件,jni 层需要根据他的方法调用即可。建议和 java 的方法保持一致,不保持一致也可以,自己在 jni 层处理好就可以。

头文件方法定义:

 //  版本号COLORCAST_API int ColorCastGetVersion(char* pOutBuf, int nOutBufSize);COLORCAST_API ColorCastResults analyzeImageColorCast(unsigned char* pData, int pw, int ph, int pchannels,double skin_ratio_threshold = 0.1, double C_threshold = 20.0,double Red_threshold = 18.0, double Green_threshold = 5.0,double Yellow_threshold = 30.0, double Blue_threshold = 5.0,double face_threshold = 0.5);COLORCAST_API ContrastColorCastResults contrastImageColorCast(unsigned char* tData, int tw, int th, int tchannels,unsigned char* pData, int pw, int ph, int pchannels,int YCrCb_cbmax = 125,int ROIwidthDiv = 6,int ROIheightDiv = 100,double USwidthRatio = 0.5,double USheightRatio = 0.01);

结构头文件:


// 偏色对比结果(双图比对)
struct ContrastColorCastResults {// 红色比对色偏指数double Red_Contrast = 999;// 绿色比对色偏指数double Green_Contrast = 999;// 黄色比对色偏指数double Yellow_Contrast = 999;// 蓝色比对色偏指数double Blue_Contrast = 999;// ROI偏色占比double ColorCast_ratio = 999;
};

2. Java 接口类定义

  这里示例图像的三种传输方式:

  1. Java 层将图像转换为 BGR 格式的 byte[],直接传给 JNI;
  2. Java 层传原始图像数据,JNI 使用 OpenCV 解码;
  3. Java 层传递文件路径,JNI 自行读取文件内容。
package com.emp.empxmrz.util;import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;/**** @title* @author shijiangyong* @date 2025/8/27 11:23**/
public class ColorCastDetExampleJni {static {System.loadLibrary("ColorCastDetExampleJni");}// 获取版本号public static native int getVersion(byte[] buffer, int bufSize);// 对比图偏色检测// 传图片数据,处理成BGR格式public static native ColorCastDetExampleJni.ContrastColorCastResults contrastImageColorCast(byte[] tData, int tw, int th, int tchannels,byte[] photoData, int pw, int ph, int pchannels,int yCrCbCbmax, int roiWidthDiv, int roiHeightDiv,double usWidthRatio, double usHeightRatio);// 传原图片数据,不转格式public static native ColorCastDetExampleJni.ContrastColorCastResults contrastImageColorCastOri(byte[] tData,byte[] photoData,int yCrCbCbmax, int roiWidthDiv, int roiHeightDiv,double usWidthRatio, double usHeightRatio);// 传图片本地路径public static native ColorCastDetExampleJni.ContrastColorCastResults contrastImageColorCastByPath(String tData,String photoData,int yCrCbCbmax, int roiWidthDiv, int roiHeightDiv,double usWidthRatio, double usHeightRatio);@Datapublic static class ContrastColorCastResults {@Schema(description = "红色比对偏色指数")public double redContrast;@Schema(description = "绿色比对偏色指数")public double greenContrast;@Schema(description = "黄色比对偏色指数")public double yellowContrast;@Schema(description = "蓝色比对偏色指数")public double blueContrast;@Schema(description = "ROI区域偏色占比")public double colorCastRatio;}
}

三、生成 JNI 头文件

构建项目之后执行下面的命令。
javah -classpath target/classes -d src/main/jni com.emp.empxmrz.util.ColorCastDetExampleJni

  这会生成 com_emp_empxmrz_util_ColorCastDetExampleJni.h 和 com_emp_empxmrz_util_ColorCastDetExampleJni_ContrastColorCastResults.h,它定义了 JNI 接口供 C++ 实现。生成之后不能随便移动类的位置或修改包名、类名等,如果必须调整的话,需要重新生成。

生成的头文件大概如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_emp_empxmrz_util_ColorCastDetExampleJni */#ifndef _Included_com_emp_empxmrz_util_ColorCastDetExampleJni
#define _Included_com_emp_empxmrz_util_ColorCastDetExampleJni
#ifdef __cplusplus
extern "C" {
#endif
/** Class:     com_emp_empxmrz_util_ColorCastDetExampleJni* Method:    getVersion* Signature: ([BI)I*/
JNIEXPORT jint JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_getVersion(JNIEnv *, jclass, jbyteArray, jint);/** Class:     com_emp_empxmrz_util_ColorCastDetExampleJni* Method:    contrastImageColorCast* Signature: ([BIII[BIIIIIIDD)Lcom/emp/empxmrz/util/ColorCastDetExampleJni/ContrastColorCastResults;*/
JNIEXPORT jobject JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCast(JNIEnv *, jclass, jbyteArray, jint, jint, jint, jbyteArray, jint, jint, jint, jint, jint, jint, jdouble, jdouble);/** Class:     com_emp_empxmrz_util_ColorCastDetExampleJni* Method:    contrastImageColorCastOri* Signature: ([B[BIIIDD)Lcom/emp/empxmrz/util/ColorCastDetExampleJni/ContrastColorCastResults;*/
JNIEXPORT jobject JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastOri(JNIEnv *, jclass, jbyteArray, jbyteArray, jint, jint, jint, jdouble, jdouble);/** Class:     com_emp_empxmrz_util_ColorCastDetExampleJni* Method:    contrastImageColorCastByPath* Signature: (Ljava/lang/String;Ljava/lang/String;IIIDD)Lcom/emp/empxmrz/util/ColorCastDetExampleJni/ContrastColorCastResults;*/
JNIEXPORT jobject JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastByPath(JNIEnv *, jclass, jstring, jstring, jint, jint, jint, jdouble, jdouble);#ifdef __cplusplus
}
#endif
#endif

四、JNI 实现(C++)

  这是 jni 的头文件实现,因为我是要调用多个算法,所以使用 vs 创建了一个解决方案,里面创建了多个项目,每个项目都是一种算法的 jni 层,根据自己的实际情况操作就可以,实现类中需要包含算法头文件和 jni 头文件,java实体的头文件不用添加。项目结构大致如下:

cpp 完整代码如下:

#include "ColorCast.h"
#include "com_emp_empxmrz_util_ColorCastDetExampleJni.h"#include <iostream>
#include <stdexcept>
#include <string>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>void native_log(const std::string& message) {std::cerr << "[NativeLog] " << message << std::endl;
}void throwJavaException(JNIEnv* env, const char* message) {jclass exceptionCls = env->FindClass("java/lang/RuntimeException");if (exceptionCls != nullptr) {env->ThrowNew(exceptionCls, message);}
}void throwIllegalArgument(JNIEnv* env, const char* message) {jclass exClass = env->FindClass("java/lang/IllegalArgumentException");if (exClass != nullptr) {env->ThrowNew(exClass, message);}
}JNIEXPORT jint JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_getVersion(JNIEnv* env, jobject obj, jbyteArray buffer, jint bufSize) {try {jboolean isCopy = JNI_FALSE;jbyte* bufPtr = env->GetByteArrayElements(buffer, &isCopy);if (bufPtr == nullptr) {throwJavaException(env, "Failed to get buffer pointer");return 0;}// 写入版本号int len = ColorCastGetVersion(reinterpret_cast<char*>(bufPtr), static_cast<int>(bufSize));// 写成功,手动同步数据回 Javaenv->ReleaseByteArrayElements(buffer, bufPtr, 0);return len; }catch (const std::exception& e) {native_log(e.what());throwJavaException(env, e.what());return 0;}
}// 构造 ContrastColorCastResults Java 对象
jobject createContrastColorCastResults(JNIEnv* env, const ContrastColorCastResults& result) {jclass cls = env->FindClass("com/emp/empxmrz/util/ColorCastDetJni$ContrastColorCastResults");if (cls == nullptr) {throwJavaException(env, "Failed to find ContrastColorCastResults class");return nullptr;}jmethodID constructor = env->GetMethodID(cls, "<init>", "()V");if (constructor == nullptr) {throwJavaException(env, "Failed to get constructor for ContrastColorCastResults");return nullptr;}jobject obj = env->NewObject(cls, constructor);env->SetDoubleField(obj, env->GetFieldID(cls, "redContrast", "D"), result.Red_Contrast);env->SetDoubleField(obj, env->GetFieldID(cls, "greenContrast", "D"), result.Green_Contrast);env->SetDoubleField(obj, env->GetFieldID(cls, "yellowContrast", "D"), result.Yellow_Contrast);env->SetDoubleField(obj, env->GetFieldID(cls, "blueContrast", "D"), result.Blue_Contrast);env->SetDoubleField(obj, env->GetFieldID(cls, "colorCastRatio", "D"), result.ColorCast_ratio);return obj;
}JNIEXPORT jobject JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCast
(JNIEnv* env, jobject obj,jbyteArray templateData, jint tw, jint th, jint tchannels,jbyteArray photoData, jint pw, jint ph, jint pchannels,jint cbmax, jint roiWidthDiv, jint roiHeightDiv,jdouble usWidthRatio, jdouble usHeightRatio) {try {jbyte* tData = env->GetByteArrayElements(templateData, nullptr);jbyte* pData = env->GetByteArrayElements(photoData, nullptr);ContrastColorCastResults result = contrastImageColorCast(reinterpret_cast<unsigned char*>(tData), tw, th, tchannels,reinterpret_cast<unsigned char*>(pData), pw, ph, pchannels,cbmax, roiWidthDiv, roiHeightDiv, usWidthRatio, usHeightRatio);env->ReleaseByteArrayElements(templateData, tData, 0);env->ReleaseByteArrayElements(photoData, pData, 0);// 将 ContrastColorCastResults 映射到 Java 对象return createContrastColorCastResults(env, result);}catch (const std::exception& e) {native_log(e.what());throwJavaException(env, e.what());return nullptr;}
}JNIEXPORT jobject JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastOri
(JNIEnv* env, jobject obj,jbyteArray templateData, jbyteArray photoData,jint cbmax, jint roiWidthDiv, jint roiHeightDiv,jdouble usWidthRatio, jdouble usHeightRatio) {try {if (templateData == nullptr) {throwIllegalArgument(env,"templateData is null");return nullptr;}if (photoData == nullptr) {throwIllegalArgument(env, "photoData is null");return nullptr;}jsize tempLen = env->GetArrayLength(templateData);if (tempLen <= 0) {throwIllegalArgument(env, "templateData is null");return nullptr;}jsize photoLen = env->GetArrayLength(photoData);if (photoLen <= 0) {throwIllegalArgument(env, "photoData is null");return nullptr;}// Zero-copy: 获取 JVM 中的数据指针(映射)jbyte* tData = env->GetByteArrayElements(templateData, nullptr);if (tData == nullptr) {throwJavaException(env, "templateData Failed to get byte array elements");return nullptr;}// Zero-copy: 获取 JVM 中的数据指针(映射)jbyte* pData = env->GetByteArrayElements(photoData, nullptr);if (pData == nullptr) {throwJavaException(env, "photoData Failed to get byte array elements");return nullptr;}// 原图// 构造一个 OpenCV Mat 来包装 byte[] 数据(不复制)cv::Mat tBuf(1, tempLen, CV_8UC1, reinterpret_cast<uchar*>(tData));// 解码为图像cv::Mat tImage = cv::imdecode(tBuf, cv::IMREAD_UNCHANGED);if (tImage.empty()) {env->ReleaseByteArrayElements(photoData, pData, JNI_ABORT);throwJavaException(env, "templateData Failed to decode image");return nullptr;}// 目标图cv::Mat pBuf(1, photoLen, CV_8UC1, reinterpret_cast<uchar*>(pData));cv::Mat pImage = cv::imdecode(pBuf, cv::IMREAD_UNCHANGED);if (pImage.empty()) {env->ReleaseByteArrayElements(templateData, tData, JNI_ABORT);throwJavaException(env, "photoData Failed to decode image");return nullptr;}ContrastColorCastResults result = contrastImageColorCast(reinterpret_cast<unsigned char*>(tImage.data), tImage.cols, tImage.rows, tImage.channels(),reinterpret_cast<unsigned char*>(pImage.data), pImage.cols, pImage.rows, pImage.channels(),cbmax, roiWidthDiv, roiHeightDiv, usWidthRatio, usHeightRatio);// 释放映射,不拷贝回 Java(JNI_ABORT)env->ReleaseByteArrayElements(templateData, tData, JNI_ABORT);env->ReleaseByteArrayElements(photoData, pData, JNI_ABORT);// 将 ContrastColorCastResults 映射到 Java 对象return createContrastColorCastResults(env, result);}catch (const std::exception& e) {native_log(e.what());throwJavaException(env, e.what());return nullptr;}
}JNIEXPORT jobject JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastByPath
(JNIEnv* env, jobject obj,jstring templateData,  jstring photoData, jint cbmax, jint roiWidthDiv, jint roiHeightDiv,jdouble usWidthRatio, jdouble usHeightRatio) {try {const char* tImagePath = env->GetStringUTFChars(templateData, nullptr);const char* pImagePath = env->GetStringUTFChars(photoData, nullptr);// 直接用 OpenCV 读取图像cv::Mat tImage = cv::imread(tImagePath);if (tImage.empty()) {env->ReleaseStringUTFChars(templateData, tImagePath); // 释放资源env->ReleaseStringUTFChars(photoData, pImagePath);throwJavaException(env, "Failed to load templateData");return nullptr;}cv::Mat pImage = cv::imread(pImagePath);if (pImage.empty()) {env->ReleaseStringUTFChars(templateData, tImagePath); // 释放资源env->ReleaseStringUTFChars(photoData, pImagePath);throwJavaException(env, "Failed to load photoData");return nullptr;}ContrastColorCastResults result = contrastImageColorCast(reinterpret_cast<unsigned char*>(tImage.data), tImage.cols, tImage.rows, tImage.channels(),reinterpret_cast<unsigned char*>(pImage.data), pImage.cols, pImage.rows, pImage.channels(),cbmax, roiWidthDiv, roiHeightDiv, usWidthRatio, usHeightRatio);env->ReleaseStringUTFChars(templateData, tImagePath);env->ReleaseStringUTFChars(photoData, pImagePath);// 将 ContrastColorCastResults 映射到 Java 对象return createContrastColorCastResults(env, result);}catch (const std::exception& e) {native_log(e.what());throwJavaException(env, e.what());return nullptr;}
}

建议添加异常处理,避免JVM 崩溃,注意资源的释放。


五、Visual Studio 配置

1. 添加包含目录

打开【项目属性】 > C/C++ > 常规 > 附加包含目录

防止编译阶段报错。


2. 添加库目录

打开【链接器】 > 常规 > 附加库目录


3. 添加依赖库

打开【链接器】 > 输入 > 附加依赖项

  告诉编译器如何调用 .dll 中的函数; 出现 JNI 方法未导出错误,可添加 .def 文件显式指定导出符号 ,内容如下,其实就是 jni 头文件方法:

LIBRARY ColorCastDetExampleJni
EXPORTSJava_com_emp_empxmrz_util_ColorCastDetExampleJni_getVersionJava_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastJava_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastOriJava_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastByPath

4.生成 DLL

  编译后会生成 ColorCastDetExampleJni.dllColorCastDetExampleJni.lib,将他们复制到 jdk 的 bin 目录或者你自己定义的目录下, java 就可以直接调用 ColorCastDetExampleJni了。


六、Java 调用测试

工具类 CustomImgUtilsImageProcessor在这篇文章里,Java 图像处理传 JNI 到 C++(OpenCV):两种高效实现方式对比
java 测试结果是否正确,也可以自己封装成接口。

service 层:

package com.emp.empxmrz.service;import com.emp.empxmrz.controller.vo.ColorCastDetExampleReq;
import com.emp.empxmrz.util.ColorCastDetExampleJni;
import com.emp.empxmrz.util.CustomImgUtils;
import com.emp.empxmrz.util.ImageProcessor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;/**** @title* @author shijiangyong* @date 2025/9/15 10:17**/
@Slf4j
@Service
public class ColorCastDetExampleJniServiceImpl implements ColorCastDetExampleJniService{@Overridepublic String getVersion() {byte[] versionBuffer = new byte[12];int result = ColorCastDetExampleJni.getVersion(versionBuffer, versionBuffer.length);String version = "获取版本号失败";if (result == 0) {version = new String(versionBuffer, StandardCharsets.UTF_8).trim();log.info("Algorithm model version number: {}", version);} else {log.warn("Failed to get version number: {} ", result);}return version;}@Overridepublic ColorCastDetExampleJni.ContrastColorCastResults contrastImageColorCast(ColorCastDetExampleReq req) {MultipartFile sourceFile = req.getSourceFile();if (sourceFile == null || sourceFile.isEmpty()) {throw new IllegalArgumentException("Source file is null or empty");}MultipartFile targetFile = req.getTargetFile();if (targetFile == null || targetFile.isEmpty()) {throw new IllegalArgumentException("Target file is null or empty");}try {byte[] sourceBytes = ImageProcessor.inputStreamToByteArray(sourceFile.getInputStream());BufferedImage sourceImage = ImageIO.read(new ByteArrayInputStream(sourceBytes));if (sourceImage == null) {throw new RuntimeException("图像读取失败");}byte[] targetBytes = ImageProcessor.inputStreamToByteArray(targetFile.getInputStream());BufferedImage targetImage = ImageIO.read(new ByteArrayInputStream(targetBytes));if (targetImage == null) {throw new RuntimeException("图像读取失败");}byte[] sourceMatrixBGR = CustomImgUtils.getMatrixBGR(sourceImage);byte[] targetMatrixBGR = CustomImgUtils.getMatrixBGR(targetImage);return ColorCastDetExampleJni.contrastImageColorCast(sourceMatrixBGR, sourceImage.getWidth(), sourceImage.getHeight(), sourceImage.getColorModel().getNumColorComponents(),targetMatrixBGR, targetImage.getWidth(), targetImage.getHeight(), targetImage.getColorModel().getNumColorComponents(),req.getYCrCbCbmax(), req.getRoiWidthDiv(), req.getRoiHeightDiv(), req.getUsWidthRatio(), req.getUsHeightRatio());} catch (IOException e) {throw new RuntimeException(e);}}@Overridepublic ColorCastDetExampleJni.ContrastColorCastResults contrastImageColorCastOri(ColorCastDetExampleReq req) {String sourceFileUrl = req.getSourceFileUrl();if (sourceFileUrl == null || sourceFileUrl.isEmpty()) {throw new IllegalArgumentException("Source file url is null or empty");}String targetFileUrl = req.getTargetFileUrl();if (targetFileUrl == null || targetFileUrl.isEmpty()) {throw new IllegalArgumentException("Target file url is null or empty");}try {byte[] sourceMatrixBGR = this.getImageBytes(sourceFileUrl);byte[] targetMatrixBGR = this.getImageBytes(targetFileUrl);return ColorCastDetExampleJni.contrastImageColorCastOri(sourceMatrixBGR, targetMatrixBGR,req.getYCrCbCbmax(), req.getRoiWidthDiv(), req.getRoiHeightDiv(), req.getUsWidthRatio(), req.getUsHeightRatio());} catch (IOException e) {throw new RuntimeException(e);}}@Overridepublic ColorCastDetExampleJni.ContrastColorCastResults contrastImageColorCastByPath(ColorCastDetExampleReq req) {String sourceFileUrl = "E:\\test\\CertifHaed.jpg";String targetFileUrl = "E:\\test\\face_big_homepage.jpg";return ColorCastDetExampleJni.contrastImageColorCastByPath(sourceFileUrl,targetFileUrl,req.getYCrCbCbmax(), req.getRoiWidthDiv(),req.getRoiHeightDiv(), req.getUsWidthRatio(), req.getUsHeightRatio());}/*** http流转BufferedImage* @param req* @return* @throws IOException*/private BufferedImage getBufferedImage(String req) throws IOException {URL url = new URL(req);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");conn.setConnectTimeout(5000);conn.setReadTimeout(10000);return ImageIO.read(conn.getInputStream());}/*** http流转Byte[]* @param req* @return* @throws IOException*/private byte[] getImageBytes(String req) throws IOException {URL url = new URL(req);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");conn.setConnectTimeout(5000);conn.setReadTimeout(10000);try (InputStream inputStream = conn.getInputStream()) {return ImageProcessor.inputStreamToByteArray(inputStream);}}
}

controller 层:

package com.emp.empxmrz.controller;import com.emp.empxmrz.controller.vo.ColorCastDetExampleReq;
import com.emp.empxmrz.service.ColorCastDetExampleJniService;
import com.emp.empxmrz.util.ColorCastDetExampleJni;
import com.emp.empxmrz.util.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/**** @title* @author shijiangyong* @date 2025/9/15 10:47**/
@Slf4j
@RestController
@AllArgsConstructor
@Tag(name = "demo示例")
@RequestMapping("/example")
public class ColorCastDetExampleJniController {private final ColorCastDetExampleJniService colorCastDetExampleJniService;@PostMapping("/getVersion")@Operation(summary = "管理后台-获取算法版本")public R<String> getVersion() {return R.ok(colorCastDetExampleJniService.getVersion());}@PostMapping("/contrast/color/castDet")@Operation(summary = "管理后台-偏色检测算法")public R<ColorCastDetExampleJni.ContrastColorCastResults> contrastImageColorCast(ColorCastDetExampleReq req) {return R.ok(colorCastDetExampleJniService.contrastImageColorCast(req));}@PostMapping("/contrast/color/castDetOri")@Operation(summary = "管理后台-偏色检测算法")public R<ColorCastDetExampleJni.ContrastColorCastResults> contrastImageColorCastOri(ColorCastDetExampleReq req) {return R.ok(colorCastDetExampleJniService.contrastImageColorCastOri(req));}@PostMapping("/contrast/color/castDetByPath")@Operation(summary = "管理后台-偏色检测算法")public R<ColorCastDetExampleJni.ContrastColorCastResults> contrastImageColorCastByPath(ColorCastDetExampleReq req) {return R.ok(colorCastDetExampleJniService.contrastImageColorCastByPath(req));}
}

调用示例:

路径去掉 Ori 就是测试上面两个入参,加上 Ori 就是测试下面两个入参,反正到了 java 层,就自己随便玩了。实体类就不贴了。

调试建议

  • 如果报错找不到 ColorCastDetExampleJni.dll,请将该 DLL 放入:
    • 项目运行目录;
    • 或者 jdk/bin 目录;
    • 或者设置 -Djava.library.path
  • 如果 JNI 函数名对应不上,请确保:
    • 包名、类名、方法名匹配;
    • DLL 导出的函数使用 extern "C"
    • JNI 方法未正确导出,可通过.def文件显式指定导出符号。

七、总结

这里介绍 JNI 技术实现了 Java 与 C++ 的深度集成。整个流程分为:
  1. 编写 Java native 接口;
  2. 使用 javah 生成 JNI 头文件;
  3. C++ 实现 JNI 方法;
  4. 配置 Visual Studio 编译动态库;
  5. Java 调用测试。

如果你不想污染自己的JDK bin,可以将 .dll.lib 放到一个统一的目录下,这样的话切换 jdk 比较方便,因为我只使用 jdk8,所以贪图方便放在了 bin 目录,但这是不规范滴 。

http://www.dtcms.com/a/482008.html

相关文章:

  • RK3588 + 银河麒麟部署 swarm 集群指南-续(自己应用程序部署)
  • 为什么我选择用 Rust 构建全栈后台管理系统?
  • 一篇文章讲清 UPD协议 与 TCP协议
  • 武邑网站建设价格wordpress 8小时
  • SSM高校职称申报系统337gs(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 深度解析:Linux sudo权限配置中的 %wheel ALL=(ALL:ALL) ALL 到底是什么意思?
  • d3.js:学习积累
  • ESLint
  • 大米CMS支付漏洞复现报告
  • SAP MM采购申请审批接口分享
  • 自定义类型:结构体、联合和枚举
  • iOS 是开源的吗?苹果系统的封闭与开放边界全解析(含开发与开心上架(Appuploader)实战)
  • 网站建设费 项目经费通用网址通用网站查询
  • 知道网站域名怎么联系wordpress插件的安装目录下
  • 网站建设价格与方案wordpress抓取别人网站
  • 服务网格 Service Mesh:微服务通信的终极进化
  • 计算机理论学习Day14
  • Spring Cloud OpenFeign + Nacos 实战教程:像调用本地方法一样调用远程微服务
  • Java求职面试: 互联网医疗场景中的缓存技术与监控运维应用
  • 【论文精读】InstanceCap:通过实例感知提升文本到视频生成效果
  • 如何将 iPhone 同步到新电脑而不会丢失数据
  • yolov8 检测
  • 男女性直接做的视频网站石家庄市城乡建设局网站
  • 有什么网站可以做婚庆视频素材平面设计公司企业logo设计
  • Python爬虫绕过Google reCAPTCHA终极指南
  • 使用docker本地部署dify
  • 极米CC极光黑金升级版无屏电视自动对焦不准如何检测
  • 一些可用于排序的函数(2542. 最大子序列的分数)
  • 灵象工具箱v0.1.5版本更新
  • 医疗网络功能虚拟化与深度强化学习的动态流量调度优化研究(上)