“函数签名”在Android NDK开发中很常见,由于Java支持重载,仅靠函数名无法唯一确定一个方法。因此,JNI提供了一套签名规则,用一个字符串来唯一确定一个Java端定义的Native方法。


具体每一种Java数据类型对应的签名字符串如下所示(来自Oracle官网JNI的介绍):



原理其实并不复杂,每种基本类型对应一个单字符签名,而类则对应为"L"+类的全路径+";",数组类型则对应"["+元素类型的签名,函数的签名则是:(各参数类型签名)+ 返回类型的签名。


搞清楚了基本原理,我们就可以尝试自定义一个Java工具类,为Java的Native函数生成签名字符串了,具体代码如下:


/**COPYRIGHTNOTICE*Copyright(C)2014,ticktick<[email protected]>*http://ticktick.blog.51cto.com/**@licenseundertheApacheLicense,Version2.0**@fileSignatureGen.java*@briefImplementajavaclassforjnisignaturegenerate**@version1.0*@authorticktick*@date2014/12/15**/packagecom.ticktick.library;importjava.util.HashMap;publicclassSignatureGen{publicstaticfinalHashMap<String,String>Primitives=newHashMap<String,String>();static{Primitives.put(Void.class.getName(),"V");Primitives.put(Boolean.class.getName(),"Z");Primitives.put(Byte.class.getName(),"B");Primitives.put(Character.class.getName(),"C");Primitives.put(Short.class.getName(),"S");Primitives.put(Integer.class.getName(),"I");Primitives.put(Long.class.getName(),"J");Primitives.put(Float.class.getName(),"F");Primitives.put(Double.class.getName(),"D");}publicstaticStringgetSignature(Classret,Class...params){StringBuilderbuilder=newStringBuilder();builder.append("(");for(Classparam:params){builder.append(getSignature(param));}builder.append(")");builder.append(getSignature(ret));returnbuilder.toString();}protectedstaticStringgetSignature(Classparam){StringBuilderbuilder=newStringBuilder();Stringname="";if(param.isArray()){name=param.getComponentType().getName();builder.append("[");}else{name=param.getName();}if(Primitives.containsKey(name)){builder.append(Primitives.get(name));}else{builder.append("L"+name.replace(".","/")+";");}returnbuilder.toString();}}


该SignatureGen类提供一个支持变参的函数getSignature来获取一个Java函数的签名字符串,第一个参数为函数返回值类型的class对象,变参为每一个函数参数类型的class对象


具体用法示例如下,打印出不同类型的函数的签名字符串。


Log.d("Signature","voidfunc()-->"+SignatureGen.getSignature(Void.class));Log.d("Signature","booleanfunc()-->"+SignatureGen.getSignature(Boolean.class));Log.d("Signature","intfunc(booleana)-->"+SignatureGen.getSignature(Integer.class,Boolean.class));Log.d("Signature","intfunc(booleana,Stringb)-->"+SignatureGen.getSignature(Integer.class,Boolean.class,String.class));Log.d("Signature","intfunc(byte[]c)-->"+SignatureGen.getSignature(Integer.class,Byte[].class));Log.d("Signature","longfunc(intn,Stringstr,intarr)-->"+SignatureGen.getSignature(Long.class,Integer.class,String.class,Integer[].class));


输出结果截屏如下:


关于JNI函数签名生成器就介绍到这儿了,原理并不复杂所以我也没有进行过多的分析,希望这个工具类能够在大家今后的项目中派上用场,有任何疑问欢迎留言或者来信[email protected]交流,或者关注我的新浪微博 @卢_俊 获取最新的文章和资讯。



更多相关文章

  1. 分支和循环(二)(零基础学习C语言)
  2. Android(安卓)5.0 Camera系统源码分析(1):CameraService启动流程
  3. 【Android架构师java原理专题详解】一;泛型原理详解
  4. SpringMVC充当Webservice与android通信
  5. android应用创建子进程的方法探究
  6. 重温String和StringBuffer
  7. Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码)[转]
  8. Android(安卓)SQlite数据库常规操作
  9. Android层接收串口数据

随机推荐

  1. Android(安卓)各种音量的获取和设置
  2. Android 自定义AlertDialog 并且4个角为
  3. Android 自定义带百分比的进度条
  4. TextView实现中间文字两侧图片的样式 和
  5. android中的BaseAdapter使用
  6. TextView设置android:textAllCaps="true"
  7. Android系统编译过程中常见问题汇总(1)
  8. Android(安卓)Studio创建Include c++项目
  9. android 添加对back按钮的处理,点击提示退
  10. Android Studio 搭建 + 第一个helloworld