1. 程式人生 > >free pascal(lazarus)版的android JNI進階篇:反向呼叫java的方法並傳遞複雜引數

free pascal(lazarus)版的android JNI進階篇:反向呼叫java的方法並傳遞複雜引數

        這篇文章雖然短暫,但耗用了筆者一天的時間搜尋各種資料,除錯了無數次,在這裡跟大家分享是想大家碰到類似問題時少走彎路,請各位轉載註明出處,http://blog.csdn.net/rocklee 。

        查閱了無數C、C++、pascal、java呼叫JNI的例子,CallxxxMethod的無引數、單一引數的例子很多,但是如果呼叫多個引數,傳遞的引數型別複雜的幾乎沒有,後來沒辦法,再回頭看看java的反射執行機制的程式碼,翻出幾個月前自己用java寫的類加密執行時的測試程式碼。本文java版的實現請看 點選開啟連結

       再對比native呼叫java jni的方法,得到一個結論就是,它們的流程是高度一致的,我能用java實現,應該也可以用native實現,但是有區別,比如通用的native中的GetMethodID就不能穿Class[]型別的引數進去,因為各種native語言對Class的處理時資料儲存方法不一樣(跟java跟是不著調了)

,但jni很聰明,它提供的用特別的字元代替這些資料型別,比java顯得更簡單了。下面先貼出java中各種資料型別跟native的轉換,以下資料是來自http://www.pacifier.com的:

There are several functions in the JNI that require, as a parameter, the signature of another function. The type of this parameter is a string. The table below shows how Java types are mapped into characters (e.g. boolean is mapped as the uppercase letter 

Z) and strings (e.g. Java String is mapped as the literal string Ljava/lang/String;). It then just becomes a matter of building these strings up based on the parameters and return types of Java methods.

Java Type Signature
boolean Z
byte B
char C
double D
float F
int I
long J
void V
object Lfully-qualified-class
;
type[] [type
method signature arg-typesret-type

Examples:

Method Signature
void f1() ()V
int f2(int, long) (IJ)I
boolean f3(int[]) ([I)B
double f4(String, int) (Ljava/lang/String;I)D
void f5(int, String [], char) (I[Ljava/lang/String;C)V

             看明白了沒有?我再舉個例子,如果我要找尋上文中Test的public String multiParametersTest(byte[] bytes,int i,int j,String s)這個方法,那麼應該這樣寫:

method := Env^^.GetMethodID(env, cls, 'multiParametersTest', '([BIILjava/lang/String;)Ljava/lang/String;');

            好了,method找到,那麼如何執行這個multiParametersTest呢? 因為網上資料沒有,我一直在用CallObjectMethodA和CallObjectMethodV去嘗試,也為了PJValue這個引數型別和va_list這個引數型別作了很多遍嘗試,對於va_list這個引數型別,連官網都沒任何解釋更不用說example了。

           好了,此文只起到拋磚引玉的作用,希望有興趣用pascal寫android NDK的朋友關注一下 http://www.pacifier.com/~mmead/jni/delphi/JEDI/DOCS/delphi-jni-2.html 這個網站,上面的資料雖然不是針對android,但是跟android的jni是高度一致的。上年oracle要狀告谷歌用了java語法侵權索賠幾個億不是無中生有的。

           題外話,為了查閱程式碼,翻了很多android影象類程式碼,發現很多方法是呼叫自帶native實現的,java的程式碼只是起到黏合作用而已,也就是說本來效率就很不錯。