Windows JNI 調試記錄

一. 前言

       最近接到一個項目,由於我們公司做水控設備項目,買的挺好的,有一個客戶需要做對需要我們設備接入他們的系統,於是需要我們提供二次開發接口,而且是Java 平臺的,通過由於這個項目我編寫的客戶端是使用C# 編寫的,並且都是所有接口都是集成到客戶端中,因此沒有預留給其他平臺調用的接口。由於Java Web 不能直接操作硬件。因此,需要我提供Java 能調用的接口,Java能調用的接口並且可以直接操作硬件,只能是C/C++ 。於是,通過JNI Java可以間接操作我們公司的USB設備,於是寫下這篇文件,記錄JNI 編寫的過程,防止下次忘記了,又需要重新學習。

二. 簡介

2.1 什麼是JNI

JNI(Java Native Interface)意爲JAVA本地調用,它允許Java代碼和其他語言寫的代碼進行交互相(一般爲C/C++),簡單的說,一種在Java虛擬機控制下執行代碼的標準機制。

2.2 JNIEnv與JavaVM 

JNIEnv 概念 : 是一個線程相關的結構體, 該結構體代表了 Java 在本線程的運行環境 ; 

JNIEnv 與 JavaVM : 注意區分這兩個概念; 
-- JavaVM : JavaVM 是 Java虛擬機在 JNI 層的代表, JNI 全局只有一個;
-- JNIEnv : JavaVM 在線程中的代表, 每個線程都有一個, JNI 中可能有很多個 JNIEnv;

JNIEnv 作用 : 
-- 調用 Java 函數 : JNIEnv 代表 Java 運行環境, 可以使用 JNIEnv 調用 Java 中的代碼;
-- 操作 Java 對象 : Java 對象傳入 JNI 層就是 Jobject 對象, 需要使用 JNIEnv 來操作這個 Java 對象;

摘自《JNI 實戰全面解析

2.3

詳細關於JNI 相關可以查看大神文章,講的非常好《JNI 實戰全面解析

三. 開發環境

        (1) JDK v1.8    (2) Eclipse 2018-12 (4.10.0)   (3) Visual Studio 2015

四. JNI 相關代碼編寫

4.1 編寫由Java native 類接口,通過javah 命令生成.h文件

java 類

package com.chen.jni;

public class JNIInterface
{
	//由java 調用c/c++ 接口打印信息
	public native void hellojni();
	
	//java 傳遞 byte 數據到C/C++ 中,並且修改
	public native void testByteArray(byte[] stream);
	
	static {
		System.loadLibrary("testjni");
	}
}

使用找到JNIInterface.java 文件,使用在Windows 控制檯中javah -classpath . -jni com.chen.JNIInterface 生成對應.h 文件

如下圖:

4.2 使用VS 創建DLL 工程,編寫JNI 到x64動態庫

4.2.1 新建Win32 控制檯工程

4.2.2 選擇DLL

4.2.3 將使用javah 生成的.h 文件拷貝到Win32 DLL 工程目錄下

4.2.4 將.h 文件添加到工程上和jni.h 相關的文件也拷貝到工程目錄下,並且添加到工程中將jni.h 和相關文件拷貝出來,是方便當工程移動到別的電腦照樣可以直接編譯。

 

4.2.5 編寫同名.cpp 文件,並且實現接口

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "com_chen_jni_JNIInterface.h"

/*
 * Class:     com_chen_jni_JNIInterface
 * Method:    hellojni
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_chen_jni_JNIInterface_hellojni
(JNIEnv *env, jobject jobj)
{
	printf("helllo jni");
}

/*
 * Class:     com_chen_jni_JNIInterface
 * Method:    testByteArray
 * Signature: ([B)V
 */
JNIEXPORT void JNICALL Java_com_chen_jni_JNIInterface_testByteArray
(JNIEnv * env,  jobject jobj,  jbyteArray jByteArray)
{
	int ik = 0;
	unsigned char data[4] = { 0 };

	env->GetByteArrayRegion(jByteArray, 0, 4, (jbyte *)data);

	printf("java to c++ data\n");
	for (ik = 0; ik < 4; ik++)
	{
		printf("data[%d] = %.2X  ", ik, data[ik]);
		data[ik] = data[ik] + 1;
	}

	env->SetByteArrayRegion(jByteArray,  0, 4, (jbyte *)data);
}

 

 

4.2.6 在C/C++ 工程配置中,添加JNI 目錄依賴

4.2.7 根據使用場景,配置工程編譯爲64位DLL 或者32 位DLL.

 

4.3 在Eclipse 中Java 通過JNI 調用C++

4.3.1 將生成的DLL 拷貝到java 工程目錄下

 

4.3.2 配置工程,增加JNI 庫支持

然後,就可以調用了。

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章