MacOS下的JNI开发

JNI (Java Native Interface,Java本地接口)是一种编程框架,使得Java虚拟机中的Java程序可以调用本地应用/或库,也可以被其他程序调用。 本地程序一般是用其它语言(C、C++或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序。
Java调用C/C++大概有这样几个步骤:

  • 编写带有native方法的Java类, 使用javac工具编译Java类
  • 使用javah来生成与native方法对应的头文件
  • 实现相应的头文件, 并编译为动态链接库(windows下是 .dll,linux下是 .so,macOS下是 .jnilib)

注意点:

  • 依赖于JNI的应用失去了Java的平台移植性(一种解决办法是为每个平台编写专门的JNI代码,然后在Java代码中,根据操作系统加载正确的JNI代码)。
  • JNI框架并没有对 non-JVM 内存提供自动垃圾回收机制,Native代码(如汇编语言)分配的内存和资源,需要其自身负责进行显式的释放。

我想用java做一些图像处理的工作,需要用到opencv,这里就以此为例.

1.编写Java类

1. 新建一个.java文件,内容如下:

package com.quickcan.watermark.util;

public class ImageProcessing {
    static {
        System.loadLibrary("image-processing");
    }

    public native void displayImage();

    public static void main(String[] args) {
        ImageProcessing imageProcessing = new ImageProcessing();
        imageProcessing.displayImage();
    }
}

2. 在ImageProcessing.java所在的目录下执行

javac ImageProcessing.java

会在当前目录下生成一个ImageProcessing.class

3. 如果ImageProcessing.java有一个package(在这里是com.quickcan.watermark.util),则需要进入这个package的根目录(在这里是com)的上级目录,执行:

javah com.quickcan.watermark.util.ImageProcessing

生成com_quickcan_watermark_util_ImageProcessing.h
内容如下:

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

#ifndef _Included_com_quickcan_watermark_util_ImageProcessing
#define _Included_com_quickcan_watermark_util_ImageProcessing
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_quickcan_watermark_util_ImageProcessing
 * Method:    displayImage
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_quickcan_watermark_util_ImageProcessing_displayImage
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

该文件定义了一个方法:Java_com_quickcan_watermark_util_ImageProcessing_displayImage,这个方法对于java文件中的native方法:public native void displayImage();.JNI在C语言中定义的规则是Java_包名_类名_方法名

2.编写C++©代码

1. 新建一个目录,用来编写.cpp(或者.c).将系统*/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/include/darwin/* 目录下的两个文件:jawt_md.h,jni_md.h复制过来,再将上一步生成的com_quickcan_watermark_util_ImageProcessing.h也复制过来.

在当前目录下新创建一个.cpp(或者.c)文件:image-processing.cpp(这个叫什么名字无所谓),用来实现com_quickcan_watermark_util_ImageProcessing.h中的方法

//
// Created by yshhuang on 2019-06-27.
//

#include "jni.h"
#include "com_quickcan_watermark_util_ImageProcessing.h"
#include <stdio.h>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

#include <iostream>
#include <string>

using namespace cv;
using namespace std;


JNIEXPORT void JNICALL Java_com_quickcan_watermark_util_ImageProcessing_displayImage
        (JNIEnv *env, jobject obj) {
    String imageName("/Volumes/develop/tool/lena.jpg");


    Mat image;
    image = imread(imageName, IMREAD_COLOR);
    if (image.empty()) {
        cout << "Could not open or find the image" << std::endl;
    }

    cout << image << endl;
    return;
};

编译这个文件:

g++ -dynamiclib -I /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/include/darwin/ $(pkg-config --cflags --libs opencv4) -std=c++14 image-processing.cpp -o libimage-processing.jnilib

2. 将上一步生成的libimage-processing.jnilib放到java.library.path下面(可以通过java代码:System.out.println(System.getProperty(“java.library.path”)); 获得).

### 3. 运行第一步创建的ImageProcessing.java的main方法,即可打印出图片各点的像素值.(如果是在IntelliJ IDEA中的java项目中运行,则把libimage-processing.jnilib放到项目的根目录也可以)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值