導航:首頁 > 編程語言 > cjava混合編程pdf

cjava混合編程pdf

發布時間:2024-07-18 15:57:45

㈠ 學習C、java、資料庫要看哪些書

朋友,你好!
看到你無比誠懇的提問,就知道你是一位非常有上進心的人,從你的文筆,能感覺到你的邏輯思維很不錯,很有潛力。雖然本人不才,不過很想盡力回答你的問題,在這里發表一下我的看法,也麻煩你讀完它們。
首先我先吐槽一下樓上的回答,有答非所問的,有兩個說了N本書的人(那些書說實話,世界上找不到幾個人是全部看完了的,說白了,不適用,理論知識,你又不是考博士去的)。
進入正題:
你學了2個月左右,如果比較充實的話,你應該已經能自學各種編程語言和思維了,你現在不斷的思索未來是個好習慣,不過在這里先提醒你一下,不要誤入歧途:有遠見可以,不過請不要好高騖遠,不要浮躁,國人的一大缺陷就是浮躁,連復興國家這種大事都想在幾十年內搞定。。。扯遠了哈。

問題一,C語言學習程度:根據你的描述,現在正在學習C語言,我推薦你認真的學完這門語言。理由:所有的語言的文法(語法)幾乎都抄自這門語言,可以說一通百通,而這門語言又很容易學習,涉及面也是最廣的,從你手上帶的電子表(單片機)到你現在用的操作系統,還有你玩的電腦游戲,無一不涉及到C語言,因為早期的所有軟體系統骨架全是C語言寫的,人們捨不得丟棄這些比較「完美」的骨架,所以一直在這骨架上搭建其他的系統和軟體,最後無法舍棄這些骨架了,所以C語言可以火到現在。再次嘮叨,請認真學習這門語言,哪怕你工作以後永遠不使用它。
推薦書籍,「譚浩強的那本C語言書」,或者目錄相近的你覺得能看明白的就行了,書不用太挑剔,都是模仿過來模仿過去,而且這些書也都只是講講文法,並不涉及到實際應用,總之,一本足矣。
問題二,JAVA方向以及書籍:你自己說過,你肯定是走JAVA方向,我也這樣認為,現在JAVA方向和C#方向是國內主流,它們門檻都比較低,我也是JAVA方向的,所以這里能多給你點建議。學完C語言以後,你學習JAVA的文法(語法)就會很輕鬆了,除了面向對象思想要理解外,其他的都能很快吸收,你應該在學習文法的同時領會面向對象思想,你看完(自己提前看吧)你們的JAVA教材後,注意多看面向對象那幾章,熟悉以後,請馬上去買本(或者網上下電子版本)《Thinking in Java》(中文名JAVA編程思想),它能徹底讓你掌握面向對象思想。之後,你不要考慮用JAVA開發桌面應用程序(在國內工作幾乎用不到),你應該開始重新撿起HTML、javascript這些WEB相關的東西了,同時自己熟悉JSP以及配置TOMCAT服務端(自己沒有WEB包或者不會建立的話先去網上下載點JSP程序,TOMCAT主要是學習如何配置那些xml配置文檔),JSP的話一定要苦學,要找幾本書看(未來的工作啊),JSP書不好推薦,隨便找幾本看看吧,都一個模子造的,都挺好的,不存在經典不經典,就是學起來有點苦澀,而且實話有點難,都是學習的別人用JAVA建立好的規則上的(說白了你不是在學JAVA,也不是在學文法,是在學應用了哦,應用前人開發的容器、規則、介面、對象,以後會理解的)。WEB編程學習,前期沒有美工支持,自己頁面設計能力不行的話,你發現你做出來的例子都很沒用很醜陋,沒什麼成就感,請注意不要放棄。當你能獨立開發JSP程序部署JSP程序到TOMCAT上以後,你可以開始學習SSH框架了(找工作的敲門磚,你最應該學的東西),SSH即struts,spring,hibernate這三個傢伙,不知道請網路查一下,相關的書籍多如牛毛,找幾本自己喜歡的吧,比如封面好看,目錄排布好點的就可以(都是一個模子),然後再買本實例書籍,專門講實例的,比如開發圖書管理系統,購物系統的SSH書籍。學完了(自己能獨立開發WEB應用了)以後JAVA方向你已經可以出山了,完全可以找工作去了,前面提到JAVA方向門檻低,是事實,熟悉SSH的都能找到工作。
問題三,資料庫:不多說哦,上面說的那些東西學的時候自然要涉及到資料庫,你會參照書上的下載並使用的,簡單的說幾個流行的,sqlserver、oracle、access、mysql這四個很流行,mysql是免費的,停止升級了已經,其他的也有免費版本,不過不好使,必須學sqlserver,其他的看公司情況,進了公司,有一段磨合期足夠你學會一種新的資料庫了,也是一通百通的東西,書籍嘛,就是網路,不會的查詢語句,都能網路到,然後就是查看資料庫自帶的聯機幫助文檔。
問題四,入行以後干什麼:按要求辦事,前面有磨合期供你適應公司以及項目,多注意溝通同時充電就好了,同時寫博客記錄你在工作時學到的技巧和碰到的問題的解決方案,積少成多,10年成精。
問題五,升職:多去考點證書,學歷要有,自考也行,職稱證書要考,充電的時候多學習管理層次的書籍,軟體工程必學~~~其他的你自然會知道的,時間有限,而且多說無益,不要依賴,相信自己,感覺你是個潛力股,加油吧朋友!
希望我的回答符合你的需要(說不定我說多了偏題了,呵呵,不好意思了)

㈡ java和c語言能混合編程嗎。

通過JNI,Java中的native方法,就是調用C/C++寫的函數

㈢ JAVA和C語言可以共同開發某個應用軟體嗎

這個是可以的,因為有混合編程這個概念的,兩者只要環境在就可以了,程序就是為實現功能的。

㈣ 用java編寫程序,定義兩個float 變數C、F。計算公式C=5/9*(F-32)輸入F輸出C

public static void main(String[] args) throws Exception {
float C;
float F;
Scanner scanner = new Scanner(System.in);
System.out.println("請輸入F:");
F = scanner.nextFloat();
C=5.0F/9*(F-32);
System.out.println("C="+C);
}

㈤ java和C#能否混合編程

請問你這樣的代碼用什麼編飢困叢譯器來尺笑編譯啊?明顯是不行的啊!不過你可以爛櫻用多文件調用的方式來搞。單一文件是肯定不行的

㈥ 如何用javac 和java 編譯運行整個Java工程

前言 本文教你怎麼用javac和java命令 以及如何利用腳本(shell或bat)方便處理 並用簡單的實例展示這些用法

IDE是把雙刃劍 它可以什麼都幫你做了 你只要敲幾行代碼 點幾下滑鼠 程序就跑起來了 用起來相當方便 你不用去關心它後面做了些什麼 執行了哪些命令 基於什麼原理 然而也是這種過分的依賴往往讓人散失了最基本的技能 當到了一個沒有IDE的地方 你便覺得無從下手 給你個代碼都不知道怎麼去跑 好比給你瓶水 你不知道怎麼打開去喝 然後活活給渴死

之前用慣了Myeclipse Java文件編譯運行的命令基本忘得一干二凈 現在項目出了原型 放到伺服器上去測試 SSH一登陸上伺服器就傻眼了 都是命令行 以前程序圖標什麼的都成了浮雲 程序放上去了不知道怎麼去編譯運行 只能補補課了 下面做下補課筆記

一 javac命令javac 用於編譯Java文件 格式為 java [options] [sourcefiles] [@files]其中 options 命令行選項 sourcefiles 一個或多個要編譯的源文件 @files 一個或多個對源文件進行列表的文件 有時候要編譯的文件很多 一個個敲命令會顯得很長 也不方便修改 可以把要編譯的源文件列在文件中 在文件名前加@ 這樣就可以對多個文件進行編譯 對編譯一個工程很有用 方便 省事

有幾個比較重要的選項 d 用於指定編譯成的class文件的存放位置 預設情況下不指定class文件的存放目錄 編譯的class文件將和源文件在同一目錄下 classpath 可以簡寫成 cp 用於搜索編譯所需的class文件 指出編譯所用到的class文件的位置 如jar zip或者其他包含class文件的目錄 指定該選項會覆蓋CLASSPATH的設定 sourcepath用於搜索編譯所需的源文件(即java文件) 指定要搜索的源文件的位置 如jar zip或其他包含java文件的目錄 需要注意windows下和linux下文件路徑分隔符和文件列表(即 classpath和 sourcepath指定的文件)分隔符的區別 windows下文件路徑分隔符用 文件列表分隔符用分號 linux下文件路徑分隔符用 / 文件列表分隔符用冒號 二 java命令java 用於執行程序 格式如下 java [options] classfile options 命令行選項 一般用於 classpath 指定要執行的文件所在的位置以及需要用到的類路徑 包括jar zip和class文件目錄 會覆蓋CLASSPATH的設定三 腳本如果要敲的命令很長 每次要編譯運行的時候都要重新敲一遍 這是一件很痛苦的事情 所以用腳本可以大大方便你的工作量 在linux下用shell腳本 windows下用bat批處理程序 因為是在linux下 我這里只是簡單介紹一下shell 關於bat批處理程序的語法自己網路一下 不難

開頭linux有很多不同的shell 通常使用bash(bourne again shell) 程序必須以下面的行開始 #!/bin/sh #!用來告訴系統用後面的參數來執行程序 這里使用的是/bin/sh要使你的腳本能夠執行 還必須讓這個文件有可執行許可權 使用下面命令更改文件許可權 chmod +x filename 注釋以#開始的句子表示注釋 一直到這行結束 多寫注釋有利於以後重新看的時候知道自己在做什麼 變數shell的腳本的變數都是字元串 不用申明類型 定義的時候直接 變數=值 即可 用到變數的的時候用 $變數 或者 ${變數} echo命令用於列印 舉個例子 #!/bin/sh # 定義變數words 值為hello world words= hello world # 列印變數words的值echo $words 命令shell腳本裡面可以直接任意使用linux命令 要用到什麼命令直接敲進去即可 記住一些常用的命令 cd 打開目錄ls l 顯示目錄信息rm fr 遞歸刪除目錄及下面的文件 不提示信息mkdir 創建目錄pwd 顯示當前路徑kill pid 強制殺掉某個進程號的進程pkill 殺掉某個名字的進程ps aux 顯示運行進程信息netstat pan 查看網路埠監聽情況四 例子下面是文件pile 用於編譯整個java工程 把編譯的文件放到指定目錄下

view plain #!/bin/sh # Define some constants ONSSERVER=ONSServer PROJECT_PATH=/root/iot oid JAR_PATH=$PROJECT_PATH/lib BIN_PATH=$PROJECT_PATH/bin SRC_PATH=$PROJECT_PATH/src/$ONSSERVER

# First remove the sources list file if it exists and then create the sources file of the project rm f $SRC_PATH/sources find $SRC_PATH/ name * java > $SRC_PATH/sources list

# First remove the ONSServer directory if it exists and then create the bin directory of ONSServer rm rf $BIN_PATH/$ONSSERVER mkdir $BIN_PATH/$ONSSERVER

# Compile the project javac d $BIN_PATH/$ONSSERVER classpath $JAR_PATH/jdom jar $JAR_PATH/oro jar @$SRC_PATH/sources list下面是文件run 用於執行程序 view plain #!/bin/sh

# Define some constants ONSSERVER=ONSServer PROJECT_PATH=/root/iot oid JAR_PATH=$PROJECT_PATH/lib BIN_PATH=$PROJECT_PATH/bin

lishixin/Article/program/Java/hx/201311/27024

㈦ C語言與JAVA

java從根本上說是c之後的一種改進語言,純面向對象的一種編程語言(當然比起Ruby還是差一點),有了C語言的基礎固然對學習java有幫助,因為在某種程度上java語言和C語言是比較接近的。但是如果沒有學習過C語言也完全沒有問題,這兩者並不存在依賴關系,直接學習java語言是完全可以的。我本然便是如此。

樓主如果沒有任何基礎,我推薦您選擇一本叫做java學習筆記的書,林信良編著的,對於初學者應該是不錯的選擇,能夠認真看完這本書的內容,通過SCJP考試應該不是問題了!

另外,我也收集了一些java和C的不同點供樓主參考:

1. Java沒有預處理指令。(如C中的#define , #include , #ifdef等)。C中的常量定義在Java中用static final來取代。

2. Java中沒有C中的全局變數。

3. Java中的主類型的size是確定的,而C中主類型的size跟平台相關。

4. Java中沒有了指針,它使用了類似的句柄來取代指針,但是Java中不允許對句柄進行加減,沒有取地址操作符之類的東東。

5. Java有垃圾收集機制,不需要自己釋放空間。

6. Java沒有goto語句。Java在C提供的控制語句基礎上增加了異常處理和標簽break和continue語句。這些可以替代goto的作用。

7. C要求一個方法或塊中使用的所有局部變數的定義在該方法或塊的最開始處定義,而Java允許這些定義在方法或塊的任意地方出現。

8. Java不要求在調用一個函數以前已經定義了該函數,可以在調用點後面定義。而C有這個要求。

9. Java不支持C中的strut 和 union類型。Java支持方法重載。

10. Java不支持C中的enum關鍵字。

11. Java不支持C中的bitfields能力。

12. Java不支持C的typedef。

13. Java不支持C的方法指針。

14. Java不支持C的可變參數表。

希望您滿意!

㈧ 如何在C/C++中調用Java

如何在C/C++中調用Java

java跨平台的特性使Java越來越受開發人員的歡迎,但也往往會聽到不少的抱怨:用Java開發的圖形用戶窗口界面每次在啟動的時候都會跳出一個控制台窗口,這個控制台窗口讓本來非常棒的界面失色不少。怎麼能夠讓通過Java開發的GUI程序不彈出Java的控制台窗口呢?其實現在很多流行的開發環境例如JBuilder、Eclipse都是使用純Java開發的集成環境。這些集成環境啟動的時候並不會打開一個命令窗口,因為它使用了JNI(Java Native Interface)的技術。通過這種技術,開發人員不一定要用命令行來啟動Java程序,可以通過編寫一個本地GUI程序直接啟動Java程序,這樣就可避免另外打開一個命令窗口,讓開發的Java程序更加專業。
JNI答應運行在虛擬機的Java程序能夠與其它語言(例如C和C++)編寫的程序或者類庫進行相互間的調用。同時JNI提供的一整套的API,答應將Java虛擬機直接嵌入到本地的應用程序中。圖1是Sun站點上對JNI的基本結構的描述。
如何在C/C++中調用Java 三聯
本文將介紹如何在C/C++中調用Java方法,並結合可能涉及到的問題介紹整個開發的步驟及可能碰到的難題和解決方法。本文所採用的工具是Sun公司創建的 Java Development Kit (JDK) 版本 1.3.1,以及微軟公司的Visual C++ 6開發環境。
環境搭建
為了讓本文以下部分的代碼能夠正常工作,我們必須建立一個完整的開發環境。首先需要下載並安裝JDK 1.3.1,其下載地址為「http://java.sun.com」。假設安裝路徑為C:JDK。下一步就是設置集成開發環境,通過Visual C++ 6的菜單Tools→Options打開選項對話框如圖2。

將目錄C:JDKinclude和C:JDKincludewin32加入到開發環境的Include Files目錄中,同時將C:JDKlib目錄添加到開發環境的Library Files目錄中。這三個目錄是JNI定義的一些常量、結構及方法的頭文件和庫文件。集成開發環境已經設置完畢,同時為了執行程序需要把Java虛擬機所用到的動態鏈接庫所在的目錄C:JDK jreinclassic設置到系統的Path環境變數中。這里需要提出的是,某些開發人員為了方便直接將JRE所用到的DLL文件直接拷貝到系統目錄下。這樣做是不行的,將導致初始化Java虛擬機環境失敗(返回值-1),原因是Java虛擬機是以相對路徑來尋找所用到的庫文件和其它一些相關文件的。至此整個JNI的開發環境設置完畢,為了讓此次JNI旅程能夠順利進行,還必須先預備一個Java類。在這個類中將用到Java中幾乎所有有代表性的屬性及方法,如靜態方法與屬性、數組、異常拋出與捕捉等。我們定義的Java程序(Demo.java)如下,本文中所有的代碼演示都將基於該Java程序,代碼如下:
package jni.test; /** * 該類是為了演示JNI如何訪問各種對象屬性等 * @author liudong */ public class Demo { //用於演示如何訪問靜態的基本類型屬性 public static int COUNT = 8; //演示對象型屬性 public String msg; PRivate int[] counts; public Demo() { this("預設構造函數"); } /** * 演示如何訪問構造器 */ public Demo(String msg) { System.out.println(":" + msg); this.msg = msg; this.counts = null; } /** * 該方法演示如何訪問一個訪問以及中文字元的處理 */ public String getMessage() { return msg; } /** * 演示數組對象的訪問 */ public int[] getCounts() { return counts; } /** * 演示如何構造一個數組對象 */ public void setCounts(int[] counts) { this.counts = counts; } /** * 演示異常的捕捉 */ public void throwExcp() throws IllegalaccessException { throw new IllegalAccessException("exception occur."); } }
初始化虛擬機
本地代碼在調用Java方法之前必須先載入Java虛擬機,而後所有的Java程序都在虛擬機中執行。為了初始化Java虛擬機,JNI提供了一系列的介面函數Invocation API。通過這些API可以很方便地將虛擬機載入到內存中。創建虛擬機可以用函數 jint JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args)。對於這個函數有一點需要注重的是,在JDK 1.1中第三個參數總是指向一個結構JDK1_ 1InitArgs, 這個結構無法完全在所有版本的虛擬機中進行無縫移植。在JDK 1.2中已經使用了一個標準的初始化結構JavaVMInitArgs來替代JDK1_1InitArgs。下面我們分別給出兩種不同版本的示例代碼。
在JDK 1.1初始化虛擬機:
#include int main() { JNIEnv *env; JavaVM *jvm; JDK1_1InitArgs vm_args; jint res; /* IMPORTANT: 版本號設置一定不能漏 */ vm_args.version = 0x00010001; /*獲取預設的虛擬機初始化參數*/ JNI_GetDefaultJavaVMInitArgs(&vm_args); /* 添加自定義的類路徑 */ sprintf(classpath, "%s%c%s", vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH); vm_args.classpath = classpath; /*設置一些其他的初始化參數*/ /* 創建虛擬機 */ res = JNI_CreateJavaVM(&jvm,&env,&vm_args); if (res < 0) { fprintf(stderr, "Can't create Java VM "); exit(1); } /*釋放虛擬機資源*/ (*jvm)->DestroyJavaVM(jvm); }
JDK 1.2初始化虛擬機:
/* invoke2.c */ #include int main() { int res; JavaVM *jvm; JNIEnv *env; JavaVMInitArgs vm_args; JavaVMOption options[3]; vm_args.version=JNI_VERSION_1_2;//這個欄位必須設置為該值 /*設置初始化參數*/ options[0].optionString = "-Djava.compiler=NONE"; options[1].optionString = "-Djava.class.path=."; options[2].optionString = "-verbose:jni";//用於跟蹤運行時的信息 /*版本號設置不能漏*/ vm_args.version = JNI_VERSION_1_2; vm_args.nOptions = 3; vm_args.options = options; vm_args.ignoreUnrecognized = JNI_TRUE; res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); if (res < 0) { fprintf(stderr, "Can't create Java VM "); exit(1); } (*jvm)->DestroyJavaVM(jvm); fprintf(stdout, "Java VM destory. "); }
為了保證JNI代碼的可移植性,建議使用JDK 1.2的方法來創建虛擬機。JNI_CreateJavaVM函數的第二個參數JNIEnv *env,就是貫穿整個JNI始末的一個參數,因為幾乎所有的函數都要求一個參數就是JNIEnv *env。
訪問類方法
初始化了Java虛擬機後,就可以開始調用Java的方法。要調用一個Java對象的方法必須經過幾個步驟:
1.獲取指定對象的類定義(jclass)
有兩種途徑來獲取對象的類定義:第一種是在已知類名的情況下使用FindClass來查找對應的類。但是要注重類名並不同於平時寫的Java代碼,例如要得到類jni.test.Demo的定義必須調用如下代碼:
jclass cls = (*env)->FindClass(env, "jni/test/Demo");//把點號換成斜杠
然後通過對象直接得到其所對應的類定義:
jclass cls = (*env)-> GetObjectClass(env, obj); //其中obj是要引用的對象,類型是jobject
2.讀取要調用方法的定義(jmethodID)
我們先來看看JNI中獲取方法定義的函數:
jmethodID (JNICALL *GetMethodID)(JNIEnv *env, jclass clazz, const char *name, const char *sig); jmethodID (JNICALL *GetStaticMethodID)(JNIEnv *env, jclass class, const char *name, const char *sig);
這兩個函數的區別在於GetStaticMethodID是用來獲取靜態方法的定義,GetMethodID則是獲取非靜態的方法定義。這兩個函數都需要提供四個參數:env就是初始化虛擬機得到的JNI環境;第二個參數class是對象的類定義,也就是第一步得到的obj;第三個參數是方法名稱;最重要的是第四個參數,這個參數是方法的定義。因為我們知道Java中答應方法的多態,僅僅是通過方法名並沒有辦法定位到一個具體的方法,因此需要第四個參數來指定方法的具體定義。但是怎麼利用一個字元串來表示方法的具體定義呢?JDK中已經預備好一個反編譯工具javap,通過這個工具就可以得到類中每個屬性、方法的定義。下面就來看看jni.test.Demo的定義:
打開命令行窗口並運行 javap -s -p jni.test.Demo 得到運行結果如下:
Compiled from Demo.java public class jni.test.Demo extends java.lang.Object { public static int COUNT; /* I */ public java.lang.String msg; /* Ljava/lang/String; */ private int counts[]; /* [I */ public jni.test.Demo(); /* ()V */ public jni.test.Demo(java.lang.String); /* (Ljava/lang/String;)V */ public java.lang.String getMessage(); /* ()Ljava/lang/String; */ public int getCounts()[]; /* ()[I */ public void setCounts(int[]); /* ([I)V */ public void throwExcp() throws java.lang.IllegalAccessException; /* ()V */ static {}; /* ()V */ }
我們看到類中每個屬性和方法下面都有一段注釋。注釋中不包含空格的內容就是第四個參數要填的內容(關於javap具體參數請查詢JDK的使用幫助)。下面這段代碼演示如何訪問jni.test.Demo的getMessage方法:
/* 假設我們已經有一個jni.test.Demo的實例obj */ jmethodID mid; jclass cls = (*env)-> GetObjectClass (env, obj);//獲取實例的類定義 mid=(*env)->GetMethodID(env,cls,"getMessage"," ()Ljava/lang/String; "); /*假如mid為0表示獲取方法定義失敗*/ jstring msg = (*env)-> CallObjectMethod(env, obj, mid); /* 假如該方法是靜態的方法那隻需要將最後一句代碼改為以下寫法即可: jstring msg = (*env)-> CallStaticObjectMethod(env, cls, mid); */
3.調用方法
為了調用對象的某個方法,可以使用函數CallMethod或者CallStaticMethod(訪問類的靜態方法),根據不同的返回類型而定。這些方法都是使用可變參數的定義,假如訪問某個方法需要參數時,只需要把所有參數按照順序填寫到方法中就可以。在講到構造函數的訪問時,將演示如何訪問帶參數的構造函數。
訪問類屬性
訪問類的屬性與訪問類的方法大體上是一致的,只不過是把方法變成屬性而已。
1.獲取指定對象的類(jclass)
這一步與訪問類方法的第一步完全相同,具體使用參看訪問類方法的第一步。
2.讀取類屬性的定義(jfieldID)
在JNI中是這樣定義獲取類屬性的方法的:
jfieldID (JNICALL *GetFieldID) (JNIEnv *env, jclass clazz, const char *name, const char *sig); jfieldID (JNICALL *GetStaticFieldID) (JNIEnv *env, jclass clazz, const char *name, const char *sig);
這兩個函數中第一個參數為JNI環境;clazz為類的定義;name為屬性名稱;第四個參數同樣是為了表達屬性的類型。前面我們使用javap工具獲取類的具體定義的時候有這樣兩行:
public java.lang.String msg; /* Ljava/lang/String; */
其中第二行注釋的內容就是第四個參數要填的信息,這跟訪問類方法時是相同的。
3.讀取和設置屬性值
有了屬性的定義要訪問屬性值就很輕易了。有幾個方法用來讀取和設置類的屬性,它們是:GetField、SetField、GetStaticField、SetStaticField。比如讀取Demo類的msg屬性就可以用GetObjectField,而訪問COUNT用GetStaticIntField,相關代碼如下:
jfieldID field = (*env)->GetFieldID(env,obj,"msg"," Ljava/lang/String;"); jstring msg = (*env)-> GetObjectField(env, cls, field);//msg就是對應Demo的msg jfieldID field2 = (*env)->GetStaticFieldID(env,obj,"COUNT","I"); jint count = (*env)->GetStaticIntField(env,cls,field2);
訪問構造函數
很多人剛剛接觸JNI的時候往往會在這一節碰到問題,查遍了整個jni.h看到這樣一個函數NewObject,它應該是可以用來訪問類的構造函數。但是該函數需要提供構造函數的方法定義,其類型是jmethodID。從前面的內容我們知道要獲取方法的定義首先要知道方法的名稱,但是構造函數的名稱怎麼來填寫呢?其實訪問構造函數與訪問一個普通的類方法大體上是一樣的,惟一不同的只是方法名稱不同及方法調用時不同而已。訪問類的構造函數時方法名必須填寫「」。下面的代碼演示如何構造一個Demo類的實例:
jclass cls = (*env)->FindClass(env, "jni/test/Demo"); /** 首先通過類的名稱獲取類的定義,相當於Java中的Class.forName方法 */ if (cls == 0) jmethodID mid = (*env)->GetMethodID(env,cls,"","(Ljava/lang/String;)V "); if(mid == 0) jobject demo = jenv->NewObject(cls,mid,0); /** 訪問構造函數必須使用NewObject的函數來調用前面獲取的構造函數的定義 上面的代碼我們構造了一個Demo的實例並傳一個空串null */
數組處理
創建一個新數組
要創建一個數組,我們首先應該知道數組元素的類型及數組長度。JNI定義了一批數組的類型jArray及數組操作的函數NewArray,其中就是數組中元素的類型。例如,要創建一個大小為10並且每個位置值分別為1-10的整數數組,編寫代碼如下:
int i = 1; jintArray array;//定義數組對象 (*env)-> NewIntArray(env, 10); for(; i<= 10; i++) (*env)->SetIntArrayRegion(env, array, i-1, 1, &i);
訪問數組中的數據
訪問數組首先應該知道數組的長度及元素的類型。現在我們把創建的數組中的每個元素值列印出來,代碼如下:
int i; /* 獲取數組對象的元素個數 */ int len = (*env)->GetArrayLength(env, array); /* 獲取數組中的所有元素 */ jint* elems = (*env)-> GetIntArrayElements(env, array, 0); for(i=0; i< len; i++) printf("ELEMENT %d IS %d ", i, elems[i]);
中文處理
中文字元的處理往往是讓人比較頭疼的事情,非凡是使用Java語言開發的軟體,在JNI這個問題更加突出。由於Java中所有的字元都是Unicode編碼,但是在本地方法中,例如用VC編寫的程序,假如沒有非凡的定義一般都沒有使用Unicode的編碼方式。為了讓本地方法能夠訪問Java中定義的中文字元及Java訪問本地方法產生的中文字元串,我定義了兩個方法用來做相互轉換。
· 方法一,將Java中文字元串轉為本地字元串
/** 第一個參數是虛擬機的環境指針第二個參數為待轉換的Java字元串定義第三個參數是本地存儲轉換後字元串的內存塊第三個參數是內存塊的大小 */ int JStringToChar(JNIEnv *env, jstring str, LPTSTR desc, int desc_len) { int len = 0; if(desc==NULLstr==NULL) return -1; //在VC中wchar_t是用來存儲寬位元組字元(UNICODE)的數據類型 wchar_t *w_buffer = new wchar_t[1024]; ZeroMemory(w_buffer,1024*sizeof(wchar_t)); //使用GetStringChars而不是GetStringUTFChars wcscpy(w_buffer,env->GetStringChars(str,0)); env->ReleaseStringChars(str,w_buffer); ZeroMemory(desc,desc_len); //調用字元編碼轉換函數(Win32 API)將UNICODE轉為ASCII編碼格式字元串 //關於函數WideCharToMultiByte的使用請參考MSDN len = WideCharToMultiByte(CP_ACP,0,w_buffer,1024,desc,desc_len,NULL,NULL); //len = wcslen(w_buffer); if(len>0 && len
· 方法二,將C的字元串轉為Java能識別的Unicode字元串
jstring NewJString(JNIEnv* env,LPCTSTR str) { if(!env !str) return 0; int slen = strlen(str); jchar* buffer = new jchar[slen]; int len = MultiByteToWideChar(CP_ACP,0,str,strlen(str),buffer,slen); if(len>0 && len < slen) buffer[len]=0; jstring js = env->NewString(buffer,len); delete [] buffer; return js; }
異常
由於調用了Java的方法,因此難免產生操作的異常信息。這些異常沒有辦法通過C++本身的異常處理機制來捕捉到,但JNI可以通過一些函數來獲取Java中拋出的異常信息。之前我們在Demo類中定義了一個方法throwExcp,下面將訪問該方法並捕捉其拋出來的異常信息,代碼如下:
/** 假設我們已經構造了一個Demo的實例obj,其類定義為cls */ jthrowable excp = 0;/* 異常信息定義 */ jmethodID mid=(*env)->GetMethodID(env,cls,"throwExcp","()V"); /*假如mid為0表示獲取方法定義失敗*/ jstring msg = (*env)-> CallVoidMethod(env, obj, mid); /* 在調用該方法後會有一個IllegalAccessException的異常拋出 */ excp = (*env)->ExceptionOccurred(env); if(excp){ (*env)->ExceptionClear(env); //通過訪問excp來獲取具體異常信息 /* 在Java中,大部分的異常信息都是擴展類java.lang.Exception,因此可以訪問excp的toString 或者getMessage來獲取異常信息的內容。訪問這兩個方法同前面講到的如何訪問類的方法是相同的。 */ }
線程和同步訪問
有些時候需要使用多線程的方式來訪問Java的方法。我們知道一個Java虛擬機是非常消耗系統的內存資源,差不多每個虛擬機需要內存大約在20MB左右。為了節省資源要求每個線程使用的是同一個虛擬機,這樣在整個的JNI程序中只需要初始化一個虛擬機就可以了。所有人都是這樣想的,但是一旦子線程訪問主線程創建的虛擬機環境變數,系統就會出現錯誤對話框,然後整個程序終止。
其實這裡面涉及到兩個概念,它們分別是虛擬機(JavaVM *jvm)和虛擬機環境(JNIEnv *env)。真正消耗大量系統資源的是jvm而不是env,jvm是答應多個線程訪問的,但是env只能被創建它本身的線程所訪問,而且每個線程必須創建自己的虛擬機環境env。這時候會有人提出疑問,主線程在初始化虛擬機的時候就創建了虛擬機環境env。為了讓子線程能夠創建自己的env,JNI提供了兩個函數:AttachCurrentThread和DetachCurrentThread。下面代碼就是子線程訪問Java方法的框架:
DWord WINAPI ThreadProc(PVOID dwParam) { JavaVM jvm = (JavaVM*)dwParam;/* 將虛擬機通過參數傳入 */ JNIEnv* env; (*jvm)-> AttachCurrentThread(jvm, (void**)&env, NULL); ......... (*jvm)-> DetachCurrentThread(jvm); }
時間
關於時間的話題是我在實際開發中碰到的一個問題。當要發布使用了JNI的程序時,並不一定要求客戶要安裝一個Java運行環境,因為可以在安裝程序中打包這個運行環境。為了讓打包程序利於下載,這個包要比較小,因此要去除JRE(Java運行環境)中一些不必要的文件。但是假如程序中用到Java中的日歷類型,例如java.util.Calendar等,那麼有個文件一定不能去掉,這個文件就是[JRE]lib zmappings。它是一個時區映射文件,一旦沒有該文件就會發現時間操作上經常出現與正確時間相差幾個小時的情況。下面是打包JRE中必不可少的文件列表(以Windows環境為例),其中[JRE]為運行環境的目錄,同時這些文件之間的相對路徑不能變。
文件名目錄 hpi.dll [JRE]in ioser12.dll [JRE]in java.dll [JRE]in net.dll [JRE]in verify.dll [JRE]in zip.dll [JRE]in jvm.dll [JRE]inclassic rt.jar [JRE]lib tzmappings [JRE]lib
由於rt.jar有差不多10MB,但是其中有很大一部分文件並不需要,可以根據實際的應用情況進行刪除。例如程序假如沒有用到Java Swing,就可以把涉及到Swing的文件都刪除後重新打包。

閱讀全文

與cjava混合編程pdf相關的資料

熱點內容
英語分類單詞pdf 瀏覽:184
打開微信時提醒微信已加密 瀏覽:346
svm演算法的論文好寫嗎 瀏覽:838
數學大辭典pdf 瀏覽:179
屏幕上滑兩次退出app怎麼取消 瀏覽:802
聯想伺服器如何開機 瀏覽:437
進入cmd後都有哪些命令 瀏覽:813
pythonmysql資料庫連接池 瀏覽:376
真三國無雙命令 瀏覽:664
警察故事在哪個app可以看 瀏覽:975
單片機8155 瀏覽:399
php音樂播放器代碼 瀏覽:753
java獲取資源文件 瀏覽:447
聯想筆記本怎麼設置私密文件夾 瀏覽:920
phpsql參數化 瀏覽:674
androiduserhandle 瀏覽:665
嬌軀命令小說 瀏覽:180
編譯android10源代碼 瀏覽:568
解壓促進睡眠音樂 瀏覽:460
分時六彩神龍指標源碼 瀏覽:222