当前位置: 代码迷 >> 综合 >> free pascal(lazarus)版的android JNI进阶篇:反向调用java的方法并传递复杂参数
  详细解决方案

free pascal(lazarus)版的android JNI进阶篇:反向调用java的方法并传递复杂参数

热度:74   发布时间:2023-12-15 20:55:07.0

        这篇文章虽然短暂,但耗用了笔者一天的时间搜索各种资料,调试了无数次,在这里跟大家分享是想大家碰到类似问题时少走弯路,请各位转载注明出处,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了。

            后来在http://www.pacifier.com/~mmead/jni/delphi/JEDI/DOCS/delphi-jni-2.html 得到启发,确定这样明确指定参数的应该要用CallXXXMethoaA。而CallXXXMethodV的应该就是对那些不定参数的调用吧,参数为Object ... args的那种。



           好了,此文只起到抛砖引玉的作用,希望有兴趣用pascal写android NDK的朋友关注一下 http://www.pacifier.com/~mmead/jni/delphi/JEDI/DOCS/delphi-jni-2.html 这个网站,上面的资料虽然不是针对android,但是跟android的jni是高度一致的。上年oracle要状告谷歌用了java语法侵权索赔几个亿不是无中生有的。


           题外话,为了查阅代码,翻了很多android图像类代码,发现很多方法是调用自带native实现的,java的代码只是起到黏合作用而已,也就是说本来效率就很不错。

            



  相关解决方案