您的当前位置:首页JNI工具

JNI工具

来源:锐游网

1.生成.h文件

import re
import os


def parse_native_methods(java_file_content):
    """解析 Java 源文件中的 native 方法声明"""
    native_methods = []
    class_name = None

    # 正则表达式来匹配类名和 native 方法
    class_pattern = re.compile(r'\bclass\s+(\w+)')
    method_pattern = re.compile(r'\b(native\s+[\w\s<>]+\s+\w+\s*\(.*?\));')

    for line in java_file_content.split('\n'):
        class_match = class_pattern.search(line)
        if class_match:
            class_name = class_match.group(1)

        method_match = method_pattern.search(line)
        if method_match:
            method_declaration = method_match.group(1)
            native_methods.append(method_declaration.strip())

    return class_name, native_methods


def jni_signature(java_class_name, method):
    """生成 JNI 方法签名"""
    # 提取返回类型和方法签名
    method_signature = re.match(r'([\w\s<>]+)\s+(\w+)\s*\((.*?)\)', method)
    if method_signature:
        return_type, method_name, parameters = method_signature.groups()
        params = parameters.split(',') if parameters else []

        # JNI 类型映射
        type_mapping = {
            'void': 'void',
            'int': 'jint',
            'long': 'jlong',
            'boolean': 'jboolean',
            'byte': 'jbyte',
            'char': 'jchar',
            'short': 'jshort',
            'float': 'jfloat',
            'double': 'jdouble',
            'String': 'jstring'
        }

        jni_params = ', '.join(['JNIEnv* env, jobject obj'] + [
            f'{type_mapping.get(p.strip().split()[0], "jobject")} {p.strip().split()[-1]}' for p in params if
            p.strip()])

        # 将 Java 类名转换为 JNI 方法名
        jni_class_name = java_class_name.replace('.', '_')
        jni_method_name = f'Java_{jni_class_name}_{method_name}'

        return f'JNIEXPORT {type_mapping.get(return_type.strip(), "jobject")} JNICALL {jni_method_name}({jni_params});'
    return None


def generate_header_file(java_class_name, native_methods, header_file_path):
    """生成 JNI 头文件"""
    with open(header_file_path, 'w') as header_file:
        header_guard = f'_{java_class_name.upper()}_H_'
        header_file.write(f'#ifndef {header_guard}\n')
        header_file.write(f'#define {header_guard}\n\n')
        header_file.write('#include <jni.h>\n\n')

        for method in native_methods:
            method_declaration = jni_signature(java_class_name, method)
            if method_declaration:
                header_file.write(f'{method_declaration}\n')

        header_file.write(f'\n#endif // {header_guard}\n')


def main():
    java_file_path = input("请输入 Java 源文件路径: ").strip()
    header_file_dir = input("请输入头文件输出目录: ").strip()

    if not os.path.exists(java_file_path):
        print(f"文件 {java_file_path} 不存在")
        return

    if not os.path.isdir(header_file_dir):
        print(f"目录 {header_file_dir} 不存在")
        return

    with open(java_file_path, 'r') as java_file:
        java_file_content = java_file.read()

    class_name, native_methods = parse_native_methods(java_file_content)
    if not class_name or not native_methods:
        print("未能解析到类名或 native 方法")
        return

    header_file_path = os.path.join(header_file_dir, f'{class_name}.h')
    generate_header_file(class_name, native_methods, header_file_path)
    print(f"头文件已生成到 {header_file_path}")


if __name__ == '__main__':
    main()

2.生成属性签名

def get_jni_type_signature(java_type):
    # 基本类型和数组类型的映射
    java_to_jni = {
        "boolean": "Z",
        "byte": "B",
        "char": "C",
        "short": "S",
        "int": "I",
        "long": "J",
        "float": "F",
        "double": "D",
        "void": "V",
        "boolean[]": "[Z",
        "byte[]": "[B",
        "char[]": "[C",
        "short[]": "[S",
        "int[]": "[I",
        "long[]": "[J",
        "float[]": "[F",
        "double[]": "[D",
        "String": "Ljava/lang/String;",
        "Object": "Ljava/lang/Object;",
        "String[]": "[Ljava/lang/String;",
        "Object[]": "[Ljava/lang/Object;"
    }

    if java_type in java_to_jni:
        return java_to_jni[java_type]

    if java_type.endswith("[]"):
        element_type = java_type[:-2]
        return f"[{get_jni_type_signature(element_type)}"
    else:
        return f"L{java_type.replace('.', '/')};"


def get_method_signature(method_signature):
    try:
        # 提取类名和方法
        class_and_method, param_and_return = method_signature.split('#')
        class_name = class_and_method.strip()

        param_and_return = param_and_return.split(':')
        method_and_params = param_and_return[0].split('(')
        method_name = method_and_params[0].strip()
        param_list = method_and_params[1][:-1].split(',') if len(method_and_params) > 1 else []
        return_type = param_and_return[1].strip() if len(param_and_return) > 1 else 'void'

        # 生成参数签名
        param_signature = ''.join([get_jni_type_signature(param.strip()) for param in param_list])

        # 生成方法签名
        return f"({param_signature}){get_jni_type_signature(return_type)}"
    except Exception as e:
        print(f"Error parsing method signature: {e}")
        return None


def main():
    while True:
        java_signature = input(
            "请输入Java方法签名(例如:com.hfengxiang.app.HelloJNI#init(android.os.Bundle, String):String,输入exit退出):")
        if java_signature.lower() == "exit":
            break
        jni_signature = get_method_signature(java_signature)
        if jni_signature:
            print(f"Java方法签名 '{java_signature}' 对应的JNI方法签名是: {jni_signature}")
        else:
            print(f"无法解析Java方法签名 '{java_signature}'")


if __name__ == "__main__":
    main()

因篇幅问题不能全部显示,请点此查看更多更全内容

Top