Java采用JNI調用VC++生成的dll

jopen 10年前發布 | 34K 次閱讀 JNI Java開發

     應項目需求,需要android調用java,java再調用C++實現android一個圖片匹配的功能,我們作為java組需要和C++和Android進行交互。下面是java和C++采用JNI的方式進行接口傳參交互,我做的一個demo并運行成功。

     什么是JNI?

     JNI 全拼是Java Native Interface,中文意思為Java本地調用。JNI標準是Java平臺的一部分,它允許java和其他語言的代碼進行交互。JNI開始是為了本地已經編譯好的語言,尤其是C和C++而設計的,我們也可以使用JNI和其他語言進行溝通,我們只要調用約定受支持了就可以了。

     什么原理?

     我們知道C++中或者C#等.net都能生成.dll類庫,而C++(或.net)中生成的.dll文件,相當于我們java程序中java源代碼通過編譯生成的.class文件,我們在java程序中直接通過code調用C++的dll文件即可。

     在 C語言中如果生成一個動態鏈接庫dll文件的時候,需要兩部分,一部分是為.h的頭文件,這個文件是負責對一些方法的聲明,而.cpp文件負責對方法的實現。而在java中,在JDK安裝目錄的include包中有個jni.h和jni_md.h,這個可以說是java發布的一個接口,在C++中可以直接使用這兩個head類型的文件對java要調用的C++方法編譯,讓java調用,并可以接收java傳遞過來的參數。直接上代碼啦。


     具體的步驟如下所示(java發布一個接口,讓C++實現乘法的功能)

     1、建立java源代碼如下所示。

     建立java project,在src下建立com包,在com包下面建立我們的java類Reliability.java,代碼如下所示。

    package com;  
    public class Reliability {  
        static {  
            try {  
                System.loadLibrary("Reliability"); // call dll  
            } catch (UnsatisfiedLinkError e) {  
                System.out.println("The load problem");  
            }  

        }  
        public native int shanfei(int i);  
        public static void main(String[] args) {  
            Reliability reliability = new Reliability();  
            System.out.print(reliability.shanfei(6));  
        }  
    }  

     2、編譯.java源文件。

     我們想實現傳遞int 整型參數來實現自己和自己相乘的結果,而實現shanfei(int p)方法的是C++。我們可以通過System.loadLibrary("Reliability")方法實現加載C++生成的dll,通過native聲明方法接口以及參數。     

     編寫好自己的Reliability.java代碼后,可以使用MyEclipse編譯為Reliability.class文件或者是直接用javac命令編譯為.class文件。

     我的使用的MyEclipse進行編譯的,會在/Reliability/bin/com文件夾中生成Reliability.class文件。


     3、用javah 命令讓Reliability.class文件生成C++需要的.h文件,也就是交給C++的接口。

     在這里需要注意的是,一定要轉到你編譯成class文件的上一級目錄進行javah命令,并且你的JDK已經配置好環境變量,這里的環境變量為 JAVA_HOME:安裝jdk bin文件夾的上一級目錄,比如我的jdk安裝在C:\java\bin....,那我的JAVA_HOME為:C:\java 。path目錄:引用JAVA_HOME并且加上\bin ,為 %JAVA_HOME%\bin 。classpath為: .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;這是一定要配置好的。然后在dos窗口如下編寫如下命令,生成給C++ .h的文件。

p1.png


     這樣在你的class文件上一級目錄中就會出現.h 的文件,并且引入到你的MyEclipse中,與com包同級。

p2.png

     4、這樣java已經給C++發布好了com_Reliability.h的頭文件,C++要去實現這個方法了。

     因為要生成dll文件,所以我們需要建立動態鏈接庫文件,如果用的是C++ 6.0環境,就是建立projects --Dynamic-LInk Library工程。

之后添加我們的com_Reliability.h文件到我們的DLL項目中,目錄結構如下所示。

p3.png

     頭文件中的代碼如下所示,com_Reliability.h。

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

    #ifndef _Included_com_Reliability  
    #define _Included_com_Reliability  
    #ifdef __cplusplus  
    extern "C" {  
    #endif  
    /* 
     * Class:     com_Reliability 
     * Method:    shanfei 
     * Signature: (I)I 
     */  
    JNIEXPORT jint JNICALL Java_com_Reliability_shanfei  
      (JNIEnv *, jclass, jint);  

    #ifdef __cplusplus  
    }  
    #endif  
    #endif  

     實現的Reliability.cpp代碼如下所示。

    #include<jni.h>  
    #include "com_Reliability.h"  
    #include<stdio.h>  
    #include<jni_md.h>  

    JNIEXPORT jint JNICALL Java_com_Reliability_shanfei(JNIEnv *, jclass, jint p)  
    {  
         int j = p*p;  
         return j;  

    }  

     切忌:.cpp中和.h中的方法名一定要相同!!!并且把從java中找到的jni.h 和jni_md.h粘貼到外部依賴文件夾,或者直接放到VC98\include文件夾中。


     5、生成dll文件

     這樣我們ctrl+F7編譯,F7在C++項目的debug中生成Reliability.dll文件,這樣我們再把這個dll文件放到java編譯的.class目錄,同時放到MyEclipse與src同級。這樣運行java的Reliability.java文件,就看到C++給我們計算的結果了。顯示如下所示。

p4.png


     總結:

     上述大致就是這個過程,在這個過程中會出現這樣或者那樣的問題,我也在不斷的去嘗試錯誤的所在,嘗試改動,最根本的就是計算機報錯了,就一定是自己哪個地方有錯誤,抱著這樣的心態,耐心的找答案、嘗試、思考,設置斷點調試,看到底是哪步出現的錯誤,最終會解決問題,讓你興奮的看到運行結果。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!