JNI_最簡單的Java調用C/C++代碼

JNI,是Java Native Interface的簡稱,中文是“Java本地調用”。通過這種技術可以做到以下兩點:

  • Java程序中的函數可以調用Native語言寫的函數,Native一般指的是C/C++編寫的函數。
  • Native程序中的函數可以調用Java層的函數,也就是說在C/C++程序中可以調用Java的函數。

本篇博客帶給童鞋們以下內容,學習內容來自(傳智播客),經由小巫總結整理:
javah工具的用法
按照C/C++頭文件來編寫C/C++源文件
將C/C++源文件編譯成動態連接庫(DLL)
在Java程序中引入動態連接庫等知識

JNI并不是什么特別神奇的東西,當初SUN推出它的目的是為了屏蔽不同操作系統平臺的差異性,通過Java語言來調用Native語言的功能模塊,避免重復制作車輪,最主要是這兩個目的。
最簡單的Java調用C/C++代碼,有以下步驟,童鞋們最好詳細閱讀,避免出現相應的錯誤:
首先在Java類中聲明一個native的方法
使用Javah命令生成native方法的聲明的C/C++頭文件
按照生成的C/C++頭文件來編寫C/C++源文件
將C/C++源文件編譯成動態鏈接庫(DLL)
將DLL文件加入到PATH環境變量下
Java類中加載DLL,然后調用聲明方法

我們現在一步一步把整個流程熟悉一遍,在Eclipse中創建一個Java項目:

筆者創建了一個命為:TestNativeCode的項目,新建包名為com.wwj.nativecode,新建類為TestNativeCode

接著在TestNativeCode類當中聲明我們的本地方法:

package com.wwj.nativecode;  
  
public class TestNativeCode {  
    // 聲明本地方法  
    public native void sayHello();  
    public static void main(String[] args) {  
//      // 加載動態鏈接庫  
//      System.loadLibrary("nativeCode");  
//      TestNativeCode nativeCode = new TestNativeCode();  
//      nativeCode.sayHello();  
  
    }  
}  

注釋掉的代碼后面很快會用到,暫時不用管。
我們聲明了本地方法之后,就可以用jdk中javah命令來為我們生成對應的頭文件,在命令可以敲入javah -help:


會顯示出javah命令的一些使用參數和意義。

找到我們Java項目TestNativeCode的路徑:筆者這里是D:\workspace\TestNativeCode

我們進入bin目錄,就可以找到對應的字節碼文件:

我們用這個來生成我們所需要的.h文件:

格式為:javah 包名.文件名

生成成功后,我們可以在當前路徑下生成的.h文件:



以上的步驟已經很清楚的介紹如何使用javah命令生成native頭文件。受用編輯器打開頭文件,有以下代碼:

/* DO NOT EDIT THIS FILE - it is machine generated */  
#include <jni.h>  
/* Header for class com_wwj_nativecode_TestNativeCode */  
  
#ifndef _Included_com_wwj_nativecode_TestNativeCode  
#define _Included_com_wwj_nativecode_TestNativeCode  
#ifdef __cplusplus  
extern "C" {  
#endif  
/* 
 * Class:     com_wwj_nativecode_TestNativeCode 
 * Method:    sayHello 
 * Signature: ()V 
 */  
JNIEXPORT void JNICALL Java_com_wwj_nativecode_TestNativeCode_sayHello  
  (JNIEnv *, jobject);  
  
#ifdef __cplusplus  
}  
#endif  
#endif  

接著在Visual studio中創建一個win32控制臺應用程序,取名為nativeCode:

創建成功后,將我們生成的頭文件剪切到C++項目中,并在項目中引入:

新建源文件:source.cpp

根據頭文件來編寫源文件:

我們發現代碼中有錯,原因是我們沒有引入“jni.h"頭文件,jni.h頭文件是在我們的jdk目錄下,include文件夾下:

把jni.h復制到項目中去,運行項目發現如下錯誤:
1>------ 已啟動生成: 項目: nativeCode, 配置: Debug Win32 ------1> source.cpp1>c:\users\administrator\documents\visual studio 2012\projects\nativecode\nativecode\jni.h(45): fatal error C1083: 無法打開包括文件:“jni_md.h”: No such file or directory========== 生成: 成功 0 個,失敗 1 個,最新 0 個,跳過 0 個 ==========

還是缺少頭文件了,jni_md.h也是在jdk中:

同樣把它添加到項目中去:

現在代碼已經沒有錯誤提示了,運行成功之后會生成我們需要的DLL文件,在對應的Debug目錄下可以找到:

接著把這個動態庫添加到PATH環境變量中去,筆者的路徑為(...\visual studio 2012\Projects\nativeCode\Debug):

最后在Eclipse中使用Java調用我們的Native代碼:

package com.wwj.nativecode;  
  
public class TestNativeCode {  
    // 聲明本地方法  
    public native void sayHello();  
    public static void main(String[] args) {  
        // 加載動態鏈接庫  
        System.loadLibrary("nativeCode");  
        TestNativeCode nativeCode = new TestNativeCode();  
        nativeCode.sayHello();  
  
    }  
}  

運行java項目,如果聲明了環境變量之后,沒有重啟Eclipse會報這樣的錯:

這時我們重啟一下Eclipse讓環境變量生效即可。

但最后調用的時候出現了這個錯誤,暫未解決:

望路過的大神,給你解決方案,動態庫是加載成功了,但調用方法是時候出現錯誤了。

2014/9/10 博文更新

很抱歉隔了這么久才來更新這篇博客,小巫之前的這個錯誤已經解決掉了,為什么會出現鏈接錯誤呢,主要還是鏈接庫的問題。

我們創建的VS項目,是Win32的平臺,而小巫的操作系統是64位的,所以我在Eclipse加載鏈接庫的時候會報錯。那么如何來解決這個問題呢,我們需要配置VS編譯的平臺,我們需要配置為x64位。

配置完之后,重新編譯運行,在項目根目錄會生成x64的目錄

然后我們把使用x64平臺生成的動態鏈接庫配置到環境變量中去:
我的路徑是:C:\Users\Administrator\Documents\visual studio 2012\Projects\nativeCode\x64\Debug

接著我們重啟Eclipse,運行我們的測試項目,這個時候就沒有錯誤了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容