<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    jni 調(diào)用C動態(tài)庫dll/so



    轉自:http://hi.baidu.com/fengying765/blog/item/7081113e5fde53e555e7233f.html


    作為主調(diào)方的Java源程序TestJNI.java如下。

    代碼清單15-4 在Linux平臺上調(diào)用C函數(shù)的例程——TestJNI.java

    1.       public class TestJNI

    2.       {

    3.          static

    4.          {

    5.            System.loadLibrary("testjni");//載入靜態(tài)庫,test函數(shù)在其中實現(xiàn)

    6.          }

    7.      

    8.          private native void testjni(); //聲明本地調(diào)用

    9.         

    10.       public void test()

    11.       {

    12.         testjni();

    13.       }

    14.   

    15.       public static void main(String args[])

    16.       {

    17.         TestJNI haha = new TestJNI();

    18.         haha.test();

    19.       }

    20.    }

    TestJNI.java聲明從libtestjni.so(注意Linux平臺的動態(tài)鏈接庫文件的擴展名是.so)中調(diào)用函數(shù)testjni()。

    在Linux平臺上,遵循JNI規(guī)范的動態(tài)鏈接庫文件名必須以“lib”開頭。例如在上面的Java程序中指定的庫文件名為“testjni”,則實際的庫文件應該命名為“libtestjni.so”。

    編譯TestJNI.java,并為C程序生成頭文件:

    java TestJNI.java

    javah TestJNI

    提供testjni()函數(shù)的testjni.c源文件如下。

    代碼清單15-5 在Linux平臺上調(diào)用C函數(shù)的例程——testjni.c

           #include <stdio.h>

          #include <TestJNI.h>  

         JNIEXPORT void JNICALL Java_TestJNI_testjni(JNIEnv *env, jobject obj){

          printf("haha---------go into c!!!\n");

         }

    編寫Makefile文件如下,JDK安裝的位置請讀者自行調(diào)整:

    libtestjni.so:testjni.o

         gcc -rdynamic -shared -o libtestjni.so testjni.o

    testjni.o:testjni.c TestJNI.h

         gcc -c testjni.c -I./ -I/usr/java/jdk1.6.0_00/include -I/usr/java/jdk1.6.0_00/include/linux

    在Makefile文件中,我們描述了最終的 libtestjin.so依賴于目標文件testjni.o,而testjni.o則依賴于testjni.c源文件和TestJNI.h頭文件。請注 意,我們在將testjni.o連接成動態(tài)鏈接庫文件時使用了“-rdynamic”選項。

    執(zhí)行make命令編譯testjni.c。Linux平臺和在Windows平臺上類似,有3種方法可以讓Java程序找到并裝載動態(tài)鏈接庫文件。

    — 將動態(tài)鏈接庫文件放置在當前路徑下。

    — 將動態(tài)鏈接庫文件放置在LD_LIBRARY_PATH環(huán)境變量所指向的路徑下。注意這一點和Windows平臺稍有區(qū)別,Windows平臺參考PATH環(huán)境變量。

    — 在啟動JVM時指定選項“-Djava.library.path”,將動態(tài)鏈接庫文件放置在該選項所指向的路徑下。

    從下一節(jié)開始,我們開始接觸到在JNI框架內(nèi)Java調(diào)用C程序的一些高級話題,包括如何傳遞參數(shù)、如何傳遞數(shù)組、如何傳遞對象等。

    各種類型數(shù)據(jù)的傳遞是跨平臺、跨語言互操作的永恒話題,更復雜的操作其實都可以分解為各種 基本數(shù)據(jù)類型的操作。只有掌握了基于各種數(shù)據(jù)類型的互操作,才能稱得上掌握了JNI開發(fā)。從下一節(jié)開始,環(huán)境和步驟不再是闡述的重點,將不再花費專門的篇 幅,例程中的關鍵點將成為我們關注的焦點。

    15.2.2.3 傳遞字符串

    到目前為止,我們還沒有實現(xiàn)Java程序向C程序傳遞參數(shù),或者C程序向Java程序傳遞參數(shù)。本例程將由Java程序向C程序傳入一個字符串,C程序?qū)υ撟址D成大寫形式后回傳給Java程序。

    Java源程序如下。

    代碼清單15-6 在Linux平臺上調(diào)用C函數(shù)的例程——Sample1

          public class Sample1

          {

          public native String stringMethod(String text);

         public static void main(String[] args)

         {

             System.loadLibrary("Sample1");

              Sample1 sample = new Sample1();

              String text   = sample.stringMethod("Thinking In Java");

           System.out.println("stringMethod: " + text);

        }

    }

    Sample1.java以“Thinking In Java”為參數(shù)調(diào)用libSample1.so中的函數(shù)stringMethod(),在得到返回的字符串后打印輸出。

    Sample1.c的源程序如下。

    代碼清單15-7 在Linux平臺上調(diào)用C函數(shù)的例程——Sample1.c

          #include <Sample1.h>

          #include <string.h>   

          JNIEXPORT jstring JNICALL Java_Sample1_stringMethod(JNIEnv *env, jobject obj, jstring string)

          {

              const char *str = (*env)->GetStringUTFChars(env, string, 0);

              char cap[128];

              strcpy(cap, str);

              (*env)->ReleaseStringUTFChars(env, string, str);

           int i=0;

           for(i=0;i<strlen(cap);i++)

             *(cap+i)=(char)toupper(*(cap+i));

           return (*env)->NewStringUTF(env, cap);

        }

    首先請注意函數(shù)頭部分,函數(shù)接收一個jstring類 型的輸入?yún)?shù),并輸出一個jstring類型的參數(shù)。jstring是jni.h中定義的數(shù)據(jù)類型,是JNI框架內(nèi)特有的字符串類型,因為jni.h在 Sample1.h中被引入,因此在Sample1.c中無須再次引入。

    程序的第4行是從JNI調(diào)用上下文中獲取UTF編碼的輸入字符,將其放在指針str所指向 的一段內(nèi)存中。第9行是釋放這段內(nèi)存。第13行是將經(jīng)過大寫轉換的字符串予以返回,這一句使用了NewStringUTF()函數(shù),將C語言的字符串指針 轉換為JNI的jstring類型。JNIEnv也是在jni.h中定義的,代表JNI調(diào)用的上下文,GetStringUTFChars()、 ReleaseStringUTFChars()和NewStringUTF()均是JNIEnv的函數(shù)。

    15.2.2.4 傳遞整型數(shù)組

    本節(jié)例程將首次嘗試在JNI框架內(nèi)啟用數(shù)組:C程序向Java程序返回一個定長的整型數(shù)組成的數(shù)組,Java程序?qū)⒃摂?shù)組打印輸出。

    Java程序的源代碼如下。

    代碼清單15-8 在Linux平臺上調(diào)用C函數(shù)的例程——Sample2

           public class Sample2

          {

         public native int[] intMethod();

          public static void main(String[] args)

          {

             System.loadLibrary("Sample2");

             Sample2 sample=new Sample2();

               int[] nums=sample.intMethod();

           for(int i=0;i<nums.length;i++)

          System.out.println(nums[i]);

       }

    }

    Sample2.java調(diào)用libSample2.so中的函數(shù)intMethod()。Sample2.c的源代碼如下。

    代碼清單15-9 在Linux平臺上調(diào)用C函數(shù)的例程——Sample2.c

          #include <Sample2.h>

         

          JNIEXPORT jintArray JNICALL Java_Sample2_intMethod(JNIEnv *env, jobject obj)

           {

          inti = 1;

           jintArray array;//定義數(shù)組對象

          array = (*env)-> NewIntArray(env, 10);

          for(; i<= 10; i++)

               (*env)->SetIntArrayRegion(env, array, i-1, 1, &i);

      

           /* 獲取數(shù)組對象的元素個數(shù) */

        int len = (*env)->GetArrayLength(env, array);

           /* 獲取數(shù)組中的所有元素 */

        jint* elems = (*env)-> GetIntArrayElements(env, array, 0);

       for(i=0; i<len; i++)

           printf("ELEMENT %d IS %d\n", i, elems[i]);

       return array;

        }

    Sample2.c涉及了兩個jni.h定義的整型數(shù) 相關的數(shù)據(jù)類型:jint和jintArray,jint是在JNI框架內(nèi)特有的整數(shù)類型。程序的第7行開辟出一個長度為10 的jint數(shù)組。然后依次向該數(shù)組中放入元素1-10。第11行至第16行不是程序的必須部分,純粹是為了向讀者們演示GetArrayLength() 和GetIntArrayElements()這兩個函數(shù)的使用方法,前者是獲取數(shù)組長度,后者則是獲取數(shù)組的首地址以便于遍歷數(shù)組。

    15.2.2.5 傳遞字符串數(shù)組

    本節(jié)例程是對上節(jié)例程的進一步深化:雖然仍然是傳遞數(shù)組,但是數(shù)組的基類換成了字符串這樣一種對象數(shù)據(jù)類型。Java程序?qū)⑾駽程序傳入一個包含中文字符的字符串,C程序并沒有處理這個字符串,而是開辟出一個新的字符串數(shù)組返回給Java程序,其中還包含兩個漢字字符串。

    Java程序的源代碼如下。

    代碼清單15-10 在Linux平臺上調(diào)用C函數(shù)的例程——Sample3

          public class Sample3

          {

           public native String[] stringMethod(String text);

         

          public static void main(String[] args) throws java.io.UnsupportedEncodingException

           {

             System.loadLibrary("Sample3");

               Sample3 sample = new Sample3();

               String[] texts = sample.stringMethod("java編程思想");

           for(int i=0;i<texts.length;i++)

            {

             texts[i]=new String(texts[i].getBytes("ISO8859-1"),"GBK");

              System.out.print( texts[i] );

           }

           System.out.println();

       }

        }

    Sample3.java調(diào)用libSample3.so中的函數(shù)stringMethod()。Sample3.c的源代碼如下:

    代碼清單15-11 在Linux平臺上調(diào)用C函數(shù)的例程——Sample3.c

           #include <Sample3.h>

          #include <string.h>

          #include <stdlib.h>

          

          #define ARRAY_LENGTH 5
        

         JNIEXPORT jobjectArray JNICALL Java_Sample3_stringMethod(JNIEnv *env, jobject obj, jstring string)

           {   

              jclass objClass = (*env)->FindClass(env, "java/lang/String");

           jobjectArray texts= (*env)->NewObjectArray(env, (jsize)ARRAY_LENGTH, objClass, 0);

           jstring jstr;

            char* sa[] = { "Hello,", "world!", "JNI", "很", "好玩" };

           int i=0;

           for(;i<ARRAY_LENGTH;i++)

            {

              jstr = (*env)->NewStringUTF( env, sa[i] );

             (*env)->SetObjectArrayElement(env, texts, i, jstr);//必須放入jstring

           }

           return texts;

       }

    第9、10行是我們需要特別關注的地方:JNI框架并 沒有定義專門的字符串數(shù)組,而是使用jobjectArray——對象數(shù)組,對象數(shù)組的基類是jclass,jclass是JNI框架內(nèi)特有的類型,相當 于Java語言中的Class類型。在本例程中,通過FindClass()函數(shù)在JNI上下文中獲取到java.lang.String的類型 (Class),并將其賦予jclass變量。

    在例程中我們定義了一個長度為5的對象數(shù)組texts,并在程序的第18行向其中循環(huán)放入預先定義好的sa數(shù)組中的字符串,當然前置條件是使用NewStringUTF()函數(shù)將C語言的字符串轉換為jstring類型。

    本例程的另一個關注點是C程序向Java程序傳遞的中文字符,在Java程序中能否正常顯 示的問題。在筆者的試驗環(huán)境中,Sample3.c是在Linux平臺上編輯的,其中的中文字符則是用支持GBK的輸入法輸入的,而Java程序采用 ISO8859_1字符集存放JNI調(diào)用的返回字符,因此在“代碼清單15-10在Linux平臺上調(diào)用C函數(shù)的例程——Sample3”的第14行中將 其轉碼后輸出。

    15.2.2.6 傳遞對象數(shù)組

    本節(jié)例程演示的是C程序向Java程序傳遞對象數(shù)組,而且對象數(shù)組中存放的不再是字符串,而是一個在Java中自定義的、含有一個topic屬性的MailInfo對象類型。

    MailInfo對象定義如下。

    代碼清單15-12 在Linux平臺上調(diào)用C函數(shù)的例程——MailInfo

         public class MailInfo {

          public String topic;

         public String getTopic()

        {

             return this.topic;

          }

    public void setTopic(String topic)

       {

        this.topic=topic;

       }

       }

    Java程序的源代碼如下。

    代碼清單15-13 在Linux平臺上調(diào)用C函數(shù)的例程——Sample4

           public class Sample4

          {

          public native MailInfo[] objectMethod(String text);

          public static void main(String[] args)

          {

              System.loadLibrary("Sample4");

            Sample4 sample = new Sample4();

              MailInfo[] mails = sample.objectMethod("Thinking In Java");

           for(int i=0;i<mails.length;i++)

             System.out.println(mails[i].topic);

       }

    }

    Sample4.java調(diào)用libSample4.so中的objectMethod()函數(shù)。Sample4.c的源代碼如下。

    代碼清單15-14 在Linux平臺上調(diào)用C函數(shù)的例程——Sample4.c

           #include <Sample4.h>

         #include <string.h>

          #include <stdlib.h>

        

          #define ARRAY_LENGTH 5

       

          JNIEXPORT jobjectArray JNICALL Java_Sample4_objectMethod(JNIEnv *env, jobject obj, jstring string)

           {  

             jclass objClass = (*env)->FindClass(env, "java/lang/Object");

           jobjectArray mails= (*env)->NewObjectArray(env, (jsize)ARRAY_LENGTH, objClass, 0);

           jclass objectClass = (*env)->FindClass(env, "MailInfo");

           jfieldID topicFieldId = (*env)->GetFieldID(env, objectClass, "topic", "Ljava/lang/String;");

        

           int i=0;

           for(;i<ARRAY_LENGTH;i++)

        {

          (*env)->SetObjectField(env, obj, topicFieldId, string);

             (*env)->SetObjectArrayElement(env, mails, i, obj);

           }

          

        return mails;

       }

    程序的第9、10行讀者們應該不會陌生,在上一節(jié)的例 程中已經(jīng)出現(xiàn)過,不同之處在于這次通過FindClass()函數(shù)在JNI上下文中獲取的是java.lang.Object的類型(Class),并將 其作為基類開辟出一個長度為5的對象數(shù)組,準備用來存放MailInfo對象。

    程序的第12、13行的目的則是創(chuàng)建一個jfieldID類型的變量,在JNI中,操作對 象屬性都是通過jfieldID進行的。第12行首先查找得到MailInfo的類型(Class),然后基于這個jclass進一步獲取其名為 topic的屬性,并將其賦予jfieldID變量。

    程序的第18、19行的目的是循環(huán)向?qū)ο髷?shù)組中放入jobject對象。 SetObjectField()函數(shù)屬于首次使用,該函數(shù)的作用是向jobject的屬性賦值,而值的內(nèi)容正是Java程序傳入的jstring變量 值。請注意在向?qū)ο髮傩再x值和向?qū)ο髷?shù)組中放入對象的過程中,我們使用了在函數(shù)頭部分定義的jobject類型的環(huán)境參數(shù)obj作為中介。至此,JNI框 架固有的兩個環(huán)境入?yún)nv和obj,我們都有涉及。

    posted on 2011-07-18 18:36 hijackwust 閱讀(4201) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     
    <2011年7月>
    262728293012
    3456789
    10111213141516
    17181920212223
    24252627282930
    31123456

    導航

    統(tǒng)計

    常用鏈接

    留言簿(6)

    隨筆檔案(57)

    友情鏈接

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 久久久久久久亚洲精品| 免费永久看黄在线观看app| 久久精品国产精品亚洲色婷婷| 一级毛片免费一级直接观看| 免费成人黄色大片| 免费的黄色网页在线免费观看| 四虎永久在线精品免费影视| 在线观看亚洲免费| 亚洲免费视频一区二区三区| 一个人晚上在线观看的免费视频| 国产亚洲自拍一区| 免费日本一区二区| 亚洲制服在线观看| 日本不卡免费新一二三区| 日日躁狠狠躁狠狠爱免费视频| 永久亚洲成a人片777777| 鲁丝片一区二区三区免费| 亚洲欧洲春色校园另类小说| 久久精品无码一区二区三区免费| 亚洲日韩精品国产3区| 亚洲 综合 国产 欧洲 丝袜 | 亚洲成av人影院| 在线观看成人免费视频不卡| 亚洲中文字幕无码mv| 亚洲国产成人精品91久久久| 国产综合免费精品久久久| 亚洲欧洲日韩综合| 波多野结衣视频在线免费观看| 中文字幕免费视频精品一| 久久久国产精品亚洲一区| 成人在线免费观看| 一级中文字幕免费乱码专区| 久久久久久亚洲精品中文字幕 | 4399影视免费观看高清直播| 亚洲熟妇无码AV| 中文字幕亚洲电影| 一二三四视频在线观看中文版免费| 色偷偷尼玛图亚洲综合| 亚洲AV人人澡人人爽人人夜夜| 成年女人看片免费视频播放器| h在线看免费视频网站男男|