android jni 函数签名,Android开发实践:JNI函数签名生成器

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

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

ac72f0362d326bff87ada2a3681422e9.png

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

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

/*

*  COPYRIGHT NOTICE

*  Copyright (C) 2014, ticktick

*  http://www.linuxidc.com/

*

*  @license under the Apache License, Version 2.0

*

*  @file    SignatureGen.java

*  @brief  Implement a java class for jni signature generate

*

*  @version 1.0

*  @author  ticktick

*  @date    2014/12/15

*

*/

package com.ticktick.library;

import java.util.HashMap;

public class SignatureGen {

public static final HashMap Primitives = new HashMap();

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");

}

public static String getSignature( Class ret, Class...params ) {

StringBuilder builder = new StringBuilder();

builder.append("(");

for( Class param : params ) {

builder.append(getSignature(param));

}

builder.append(")");

builder.append(getSignature(ret));

return builder.toString();

}

protected static String getSignature( Class param ) {

StringBuilder builder = new StringBuilder();

String name = "";

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(".","/")+";");

}

return builder.toString();

}

}

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

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

Log.d("Signature","void func() --> " + SignatureGen.getSignature(Void.class));

Log.d("Signature","boolean func() --> " + SignatureGen.getSignature(Boolean.class));

Log.d("Signature","int func(boolean a) --> " + SignatureGen.getSignature(Integer.class,Boolean.class));

Log.d("Signature","int func(boolean a,String b) --> " + SignatureGen.getSignature(Integer.class,Boolean.class,String.class));

Log.d("Signature","int func(byte[] c) --> " + SignatureGen.getSignature(Integer.class,Byte[].class));

Log.d("Signature","long func(int n,String str,int arr) -->" + SignatureGen.getSignature(Long.class,Integer.class,String.class,Integer[].class));

输出结果截屏如下:

144a9b5a106535456485c41c3118639c.png

关于JNI函数签名生成器就介绍到这儿了,原理并不复杂所以我也没有进行过多的分析,希望这个工具类能够在大家今后的项目中派上用场,有任何疑问欢迎留言或者来信lujun.hust@gmail.com交流。

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值