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

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

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

    隨筆 - 63  文章 - 0  trackbacks - 0
    <2009年5月>
    262728293012
    3456789
    10111213141516
    17181920212223
    24252627282930
    31123456

    常用鏈接

    留言簿(2)

    隨筆分類

    隨筆檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    Java代碼
    1. 簡單介紹及應用如下:    
    2.   一、JAVA中所需要做的工作    
    3.   在JAVA程序中,首先需要在類中聲明所調用的庫名稱,如下:    
    4.   
    5. static {    
    6. System.loadLibrary(“goodluck”);    
    7. }   
    8.   
    9.   
    10.   在這里,庫的擴展名字可以不用寫出來,究竟是DLL還是SO,由系統自己判斷。    
    11.   
    12.   還需對將要調用的方法做本地聲明,關鍵字為native。且只需要聲明,而不需要具體實現。如下:    
    13.   
    14. public native static void set(int i);    
    15. public native static int get();   
    16.   
    17.   
    18.   然后編譯該JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就會生成C/C++的頭文件。    
    19.   
    20.   例如程序testdll.java,內容為:    
    21.   
    22. public class testdll    
    23. {    
    24. static    
    25. {    
    26. System.loadLibrary("goodluck");    
    27. }    
    28. public native static int get();    
    29. public native static void set(int i);    
    30. public static void main(String[] args)    
    31. {    
    32. testdll test = new testdll();    
    33. test.set(10);    
    34. System.out.println(test.get());    
    35. }    
    36. }   
    37.   
    38.   
    39.   用javac testdll.java編譯它,會生成testdll.class。    
    40.   再用javah testdll,則會在當前目錄下生成testdll.h文件,這個文件需要被C/C++程序調用來生成所需的庫文件。    
    41.   
    42.   二、C/C++中所需要做的工作    
    43.   對于已生成的.h頭文件,C/C++所需要做的,就是把它的各個方法具體的實現。然后編譯連接成庫文件即可。再把庫文件拷貝到JAVA程序的路徑下面,就可以用JAVA調用C/C++所實現的功能了。    
    44.   接上例子。我們先看一下testdll.h文件的內容:    
    45.   
    46. /* DO NOT EDIT THIS FILE - it is machine generated */    
    47. #include    
    48. /* Header for class testdll */    
    49. #ifndef _Included_testdll    
    50. #define _Included_testdll    
    51. #ifdef __cplusplus    
    52. extern "C" {    
    53. #endif    
    54. /*   
    55. * Class: testdll   
    56. * Method: get   
    57. * Signature: ()I   
    58. */    
    59. JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);    
    60. /*   
    61. * Class: testdll   
    62. * Method: set   
    63. * Signature: (I)V   
    64. */    
    65. JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);    
    66. #ifdef __cplusplus    
    67. }    
    68. #endif    
    69. #endif   
    70.   
    71.   
    72.   在具體實現的時候,我們只關心兩個函數原型    
    73.   JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass); 和    
    74.   JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);   
    75.   
    76.   這里JNIEXPORT和JNICALL都是JNI的關鍵字,表示此函數是要被JNI調用的。而jint是以JNI為中介使JAVA的int類型與本 地的int溝通的一種類型,我們可以視而不見,就當做int使用。函數的名稱是JAVA_再加上java程序的package路徑再加函數名組成的。參數 中,我們也只需要關心在JAVA程序中存在的參數,至于JNIEnv*和jclass我們一般沒有必要去碰它。    
    77.   
    78.   好,下面我們用testdll.cpp文件具體實現這兩個函數:    
    79.   
    80. #include "testdll.h"    
    81. int i = 0;    
    82. JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)    
    83. {    
    84. return i;    
    85. }    
    86. JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)    
    87. {    
    88. i = j;    
    89. }   
    90.   
    91.   
    92.   編譯連接成庫文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名稱要與JAVA中需要調用的一致,這里就是goodluck.dll 。把goodluck.dll拷貝到testdll.class的目錄下,java testdll運行它,就可以觀察到結果了。    
    93.   我的項目比較復雜,需要調用動態鏈接庫,這樣在JNI傳送參數到C程序時,需要對參數進行處理轉換。才可以被C程序識別。   
    94.   大體程序如下:   
    95.   
    96. public class SendSMS {    
    97. static    
    98. {    
    99.   
    100.   
    101.     
    102. System.out.println(System.getProperty("java.library.path"));    
    103. System.loadLibrary("sms");    
    104. }    
    105. public native static int SmsInit();    
    106. public native static int SmsSend(byte[] mobileNo, byte[] smContent);    
    107. }    
    108.   
    109.   在這里要注意的是,path里一定要包含類庫的路徑,否則在程序運行時會拋出異常:   
    110.   java.lang.UnsatisfiedLinkError: no sms in java.library.path   
    111.   at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1491)   
    112.   at java.lang.Runtime.loadLibrary0(Runtime.java:788)   
    113.   at java.lang.System.loadLibrary(System.java:834)   
    114.   at com.mobilesoft.sms.mobilesoftinfo.SendSMS.(SendSMS.java:14)   
    115.   at com.mobilesoft.sms.mobilesoftinfo.test.main(test.java:18)   
    116.   Exception in thread "main"  
    117.   
    118.   指引的路徑應該到.dll文件的上一級,如果指到.dll,則會報:   
    119.   java.lang.UnsatisfiedLinkError: C:\sms.dll: Can't find dependent libraries   
    120.   at java.lang.ClassLoader$NativeLibrary.load(Native Method)   
    121.   at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1560)   
    122.   at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1485)   
    123.   at java.lang.Runtime.loadLibrary0(Runtime.java:788)   
    124.   at java.lang.System.loadLibrary(System.java:834)   
    125.   at com.mobilesoft.sms.mobilesoftinfo.test.main(test.java:18)   
    126.   Exception in thread "main"  
    127.   
    128.   通過編譯,生成com_mobilesoft_sms_mobilesoftinfo_SendSMS.h頭文件。(建議使用Jbuilder進行編 譯,操作比較簡單!)這個頭文件就是Java和C之間的紐帶。要特別注意的是方法中傳遞的參數jbyteArray,這在接下來的過程中會重點介紹。   
    129.   
    130. /* DO NOT EDIT THIS FILE - it is machine generated */    
    131. #include    
    132. /* Header for class com_mobilesoft_sms_mobilesoftinfo_SendSMS */    
    133. #ifndef _Included_com_mobilesoft_sms_mobilesoftinfo_SendSMS    
    134. #define _Included_com_mobilesoft_sms_mobilesoftinfo_SendSMS    
    135. #ifdef __cplusplus    
    136. extern "C" {    
    137. #endif    
    138. /*   
    139. * Class: com_mobilesoft_sms_mobilesoftinfo_SendSMS   
    140. * Method: SmsInit   
    141. * Signature: ()I   
    142. */    
    143. JNIEXPORT jint JNICALL Java_com_mobilesoft_sms_mobilesoftinfo_SendSMS_SmsInit    
    144. (JNIEnv *, jclass);    
    145. /*   
    146. * Class: com_mobilesoft_sms_mobilesoftinfo_SendSMS   
    147. * Method: SmsSend   
    148. * Signature: ([B[B)I   
    149. */    
    150. JNIEXPORT jint JNICALL Java_com_mobilesoft_sms_mobilesoftinfo_SendSMS_SmsSend    
    151. (JNIEnv *, jclass, jbyteArray, jbyteArray);    
    152. #ifdef __cplusplus    
    153. }    
    154. #endif    
    155. #endif   
    156.   
    157.   
    158.   
    159.   對于我要調用的C程序的動態鏈接庫,C程序也要提供一個頭文件,sms.h。這個文件將要調用的方法羅列了出來。   
    160.   
    161. /*   
    162. * SMS API   
    163. * Author: yippit   
    164. * Date: 2004.6.8   
    165. */    
    166. #ifndef MCS_SMS_H    
    167. #define MCS_SMS_H    
    168. #define DLLEXPORT __declspec(dllexport)    
    169. /*sms storage*/    
    170. #define SMS_SIM 0    
    171. #define SMS_MT 1    
    172. /*sms states*/    
    173. #define SMS_UNREAD 0    
    174. #define SMS_READ 1    
    175. /*sms type*/    
    176. #define SMS_NOPARSE -1    
    177. #define SMS_NORMAL 0    
    178. #define SMS_FLASH 1    
    179. #define SMS_MMSNOTI 2    
    180. typedef struct tagSmsEntry {    
    181. int index; /*index, start from 1*/    
    182. int status; /*read, unread*/    
    183. int type; /*-1-can't parser 0-normal, 1-flash, 2-mms*/    
    184. int storage; /*SMS_SIM, SMS_MT*/    
    185. char date[24];    
    186. char number[32];    
    187. char text[144];    
    188. } SmsEntry;    
    189. DLLEXPORT int SmsInit(void);    
    190. DLLEXPORT int SmsSend(char *phonenum, char *content);    
    191. DLLEXPORT int SmsSetSCA(char *sca);    
    192. DLLEXPORT int SmsGetSCA(char *sca);    
    193. DLLEXPORT int SmsSetInd(int ind);    
    194. DLLEXPORT int SmsGetInd(void);    
    195. DLLEXPORT int SmsGetInfo(int storage, int *max, int *used);    
    196. DLLEXPORT int SmsSaveFlash(int flag);    
    197. DLLEXPORT int SmsRead(SmsEntry *entry, int storage, int index);    
    198. DLLEXPORT int SmsDelete(int storage, int index);    
    199. DLLEXPORT int SmsModifyStatus(int storage, int index); /*unread -> read*/    
    200. #endif   
    201.   
    202.   
    203.   在有了這兩個頭文件之后,就可以進行C程序的編寫了。也就是實現對JNI調用的兩個方法。在網上的資料中,由于調用的方法實現的都比較簡單,(大多是打印字符串等)所以避開了JNI中最麻煩的部分,也是最關鍵的部分,參數的傳遞。     
    204. 由于Java和C的編碼是不同的,所以傳遞的參數是要進行再處理,否則C程序是會對參數在編譯過程中提出警告,例如;warning C4024: 'SmsSend' : different types for formal and actual parameter 2等。   
    205.   Sms.c的程序如下:   
    206.   
    207. #include "sms.h"    
    208. #include "com_mobilesoft_sms_mobilesoftinfo_SendSMS.h"    
    209. JNIEXPORT jint JNICALL Java_com_mobilesoft_sms_mobilesoftinfo_SendSMS_SmsInit(JNIEnv * env, jclass jobject)    
    210. {    
    211. return SmsInit();    
    212. }    
    213.   
    214. JNIEXPORT jint JNICALL Java_com_mobilesoft_sms_mobilesoftinfo_SendSMS_SmsSend(JNIEnv * env, jclass jobject, jbyteArray mobileno, jbyteArray smscontent)    
    215. {    
    216. char * pSmscontent ;    
    217. //jsize theArrayLengthJ = (*env)->GetArrayLength(env,mobileno);    
    218. jbyte * arrayBody = (*env)->GetByteArrayElements(env,mobileno,0);    
    219. char * pMobileNo = (char *)arrayBody;    
    220. printf("[%s]\n ", pMobileNo);    
    221. //jsize size = (*env)->GetArrayLength(env,smscontent);    
    222. arrayBody = (*env)->GetByteArrayElements(env,smscontent,0);    
    223. pSmscontent = (char *)arrayBody;    
    224. printf("<%s>\n", pSmscontent);    
    225. return SmsSend(pMobileNo,pSmscontent);    
    226. }   
    227.   
    228.   
    229.   
    230.   對于C或C++,在程序上是會有稍微的不同,這可以由讀者對其進行適當的修改。這里要注意的是GetArrayLength,GetByteArrayElements等這些JNI中已經包含的方法,這些方法是專門對轉換參數類型而提供的。具體的方法有很多,在下一篇中會做專門的介紹。   
    231.   在完成了上述的文件后,可以對sms.c進行編譯,生成.dll文件(建議在release中編譯,這樣動態鏈接庫的容積會比較小!)   
    232.   完成.dll文件的編譯后,就可以在Java中調用C程序中的方法了。例如文件test.java   
    233.   
    234. public class test {    
    235. public test() {    
    236. }    
    237. public static void main(String[] args) {    
    238. byte[] mobileno = {    
    239. 0x310x330x360x360x310x360x330x300x360x360x370x00};    
    240. String smscontentemp = "早上好";    
    241. byte[] temp = {0};    
    242. try {    
    243. byte[] smscontentdb = smscontentemp.getBytes("gbk");    
    244. byte[] smscontent = new byte[smscontentdb.length + temp.length];    
    245. System.arraycopy(smscontentdb, 0, smscontent, 0, smscontentdb.length);    
    246. System.arraycopy(temp, 0, smscontent, smscontentdb.length, temp.length);    
    247. SendSMS sendSMS = new SendSMS();    
    248. sendSMS.SmsInit();    
    249. if (sendSMS.SmsSend(mobileno, smscontent) >= 0) {    
    250. System.out.println("chenggong !");    
    251. }    
    252. else {    
    253. System.out.println("shibai !");    
    254. }    
    255. }catch (Exception ex) {}    
    256. }    
    257. }   
    258.   
    259.   
    260.   
    261.   在這個文件中要注意的有一點,就是在傳遞字節數組到C程序中時,最后的結尾一定要以0結束。這是一個偷懶的做法,不過是個有效的做法。因為大多數情況 下,接口是由第三方提供的。所以我們一般是不知道在C的方法里,具體是怎么處理參數的。而C又是要求數組是有長度。所以,在Java中,如果你不想寫程序 傳數組的長度,那么在數組中以0結尾就是最方便的方法了。當然,如果有更好的方法也希望大家提出。   
    262.   
    263.   到這里,一個完整的Java通過JNI調用動態鏈接庫的程序就完成了。實際上也不是很復雜。只要多注意一下細節,是很容易得出來的。  
    posted on 2009-05-07 11:04 lanxin1020 閱讀(172) 評論(0)  編輯  收藏 所屬分類: j2se
    主站蜘蛛池模板: 日韩国产精品亚洲а∨天堂免| 西西人体44rt高清亚洲| 亚洲国产一区二区三区在线观看| 国产高清免费视频| 亚洲香蕉久久一区二区三区四区| 黄页网站免费观看| 亚洲精品无码久久久久YW| 日本不卡高清中文字幕免费| 窝窝影视午夜看片免费| 亚洲色一色噜一噜噜噜| 在线涩涩免费观看国产精品 | 97在线观看永久免费视频| 亚洲乱码卡三乱码新区| 毛片a级毛片免费播放下载| 国产精品亚洲а∨无码播放不卡| 日韩亚洲精品福利| a级毛片无码免费真人久久| 久久水蜜桃亚洲av无码精品麻豆| 希望影院高清免费观看视频| 亚洲天然素人无码专区| 亚洲国产专区一区| 久久aa毛片免费播放嗯啊| 亚洲国产精品久久丫| 国产99视频免费精品是看6| 成人妇女免费播放久久久| 亚洲小视频在线观看| 成年人性生活免费视频| 色爽黄1000部免费软件下载| 亚洲国产精品VA在线观看麻豆| 国产精品爱啪在线线免费观看| 亚洲色大成WWW亚洲女子| 中文字幕亚洲不卡在线亚瑟| 24小时在线免费视频| 亚洲AV无码专区国产乱码不卡| 伊人婷婷综合缴情亚洲五月| 91精品啪在线观看国产线免费| 日韩色视频一区二区三区亚洲 | 亚美影视免费在线观看| 亚洲的天堂av无码| 亚洲国产午夜中文字幕精品黄网站| 国产羞羞的视频在线观看免费|