2015年3月23日 星期一

[Java] 用JNA 呼叫C的函式

參考資料來源

http://teddy-chen-tw.blogspot.tw/2009/07/javanative-code.html


Java中我們可以透過JNI(Java Native Interface) 來呼叫DLL或是Linux裡的lib檔案,

JNA(Java Native Access),可以讓我們簡化JNI的操作,讓它就像呼叫函式一樣簡單,不

必自己再去弄一個head檔出來。


1. 首先到這裡下載JNA,點選右下角的Download ZIP

https://github.com/twall/jna





















2.把ZIP檔解壓縮


3.開啟Netbeans ,新建一個Java專案。





























4.把剛才的JNA加入Libraries (jna-master/dist/jna.jar)










































5.點選Files










6.新增一個資料夾叫lib











































7.把jna.jar複制到lib資料夾中












8.程式碼如下

 
package jna.test;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

/**
 *
 * @author 北七部落
 */
public class JNATest {

    //JNA所需要的介面
    public interface C_Library extends Library
    {
        //先判別系統是否為windows,windows需要呼叫msvcrt,linux則呼叫C
        String os_c=Platform.isWindows()?"msvcrt":"c";
        //初始化實體(載入所需要的dll,msvcrt.dll or c.lib)
        C_Library INSTANCE=(C_Library)
                Native.loadLibrary(os_c, C_Library.class);
        
        /* 要用到的C語言函式,在C語言中是這樣定義
         *  printf(格式化輸出數據)
            相關函數
            scanf,snprintf
            表頭文件
            #include
            定義函數
            int printf(const char * format,.............);
            函數說明
            printf()會根據參數format字符串來轉換並格式化數據,
            然後將結果寫出到標準輸出設備,
            直到出現字符串結束('\0')為止。
         *  資料來源 
            http://people.cs.nctu.edu.tw/~yslin/library/
            linuxc/main.htm
         *  要用用Java的資料型態去對應。
         */
        int printf(String format ,Object... args);
    }
    
    public static void main(String[] args) {
        
        //調用C言函的print
        C_Library.INSTANCE.printf("hi,I am %s , 
        %d year old , I like this float %f\n", 
        "bert",20,3.1415);
    }    
}

9.執行結果









10.我們再來試一下呼叫一下system函式
 
package jna.test;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

/**
 *
 * @author 北七部落
 */
public class JNATest {

    //JNA所需要的介面
    public interface C_Library extends Library
    {
        //先判別系統是否為windows,windows需要呼叫msvcrt,linux則呼叫C
        String os_c=Platform.isWindows()?"msvcrt":"c";
        //初始化實體(載入所需要的dll,msvcrt.dll or c.lib)
        C_Library INSTANCE=(C_Library)
                Native.loadLibrary(os_c, C_Library.class);
        
        /* 要用到的C語言函式,在C語言中是這樣定義
         *  printf(格式化輸出數據)
            相關函數
            scanf,snprintf
            表頭文件
            #include
            定義函數
            int printf(const char * format,.............);
            函數說明
            printf()會根據參數format字符串來轉換並格式化數據,
            然後將結果寫出到標準輸出設備,直到出現字符串結束('\0')為止。
         *  資料來源 http://people.cs.nctu.edu.tw/~yslin/library/
            linuxc/main.htm
         *  要用用Java的資料型態去對應。
         */
        int printf(String format ,Object... args);
        
        
        /*要用到的C語言函式,在C語言中是這樣定義
        system(執行shell 命令)
        相關函數
        fork,execve,waitpid,popen
        表頭文件
        #include
        定義函數
        int system(const char * string);
        函數說明
        system()會調用fork()產生子進程,由子進程來調用
        /bin/sh-c string來執行參數string字符串所代表的命令,
        此命令執行完後隨即返回原調用的進程。
        資料來源 http://people.cs.nctu.edu.tw/~yslin/library/
        linuxc/main.htm
         *  要用用Java的資料型態去對應。
        */
        int system(String shell);
    }
    
    public static void main(String[] args) {
        
        //調用C語言的system 來查詢目錄下的檔案
        String os_dir=Platform.isWindows()?"dir":"ls";
        C_Library.INSTANCE.system(os_dir);
        //調用C言函的print
        C_Library.INSTANCE.printf("hi,I am %s , %d year old , 
        I like this float %f\n", "bert",20,3.1415);
    }    
}


11.執行結果

















12.補充

msvcrt.dll是微軟在windows操作系統中提供的C語言運行庫執行文件(Microsoft C Runtime Library),其中提供了printf,malloc,strcpy等C語言庫函數的具體運行實現,並且為使用C/C++(Vc)編繹的程序提供了初始化(如獲取命令行參數)以及退出等功能。

資料來源
http://baike.baidu.com/view/665378.htm


這段程式碼我在win 7 以及mac 10.10 運行是正常的。

沒有留言:

張貼留言