使用python正则表达式自动生成android jni方法签名
我使用SWIG为Irrlicht C/C++3D引擎生成了一些本机JNI函数接口,我得到了一堆java代理类和一个中间C/C++文件,这些文件实现了java本机函数来粘合java代理类和Irrlicht C/C++3D引擎 所有java代理类都是在包net.sf.jirr中生成的。生成的java本机方法在net.sf.jirr.JirrJNI类中定义 由于SWIG生成的c/c++jni函数的名称不符合默认的android jni函数调用约定,因此我需要手动将这些java本机方法注册到相应的c/c++jni函数中 i、 e.以生成的java本机方法net.sf.jirr.JirrJNI.SColor_setRed为例: 生成的java本机方法定义为:使用python正则表达式自动生成android jni方法签名,android,python,regex,java-native-interface,irrlicht,Android,Python,Regex,Java Native Interface,Irrlicht,我使用SWIG为Irrlicht C/C++3D引擎生成了一些本机JNI函数接口,我得到了一堆java代理类和一个中间C/C++文件,这些文件实现了java本机函数来粘合java代理类和Irrlicht C/C++3D引擎 所有java代理类都是在包net.sf.jirr中生成的。生成的java本机方法在net.sf.jirr.JirrJNI类中定义 由于SWIG生成的c/c++jni函数的名称不符合默认的android jni函数调用约定,因此我需要手动将这些java本机方法注册到相应的c/c
public final static native void SColor_setRed(long jarg1, SColor jarg1_, long jarg2);
SWIGEXPORT void JNICALL Java_net_sf_jirr_JirrJNI_SColor_1setRed(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2)
#define SET_A_JNI_METHOD(name, signature, func_ptr) \
{ (char*)#name, (char*)signature, (void*)func_ptr }
const char* JNI_REG_CLASS = "net/sf/jirr/JirrJNI";
JNINativeMethod JNI_METHODS[] = { SET_A_JNI_METHOD(SColor_setRed, "(JLnet/sf/jirr/SColor;J)V", Java_net_sf_jirr_JirrJNI_SColor_1setRed), ......};
int JNI_METHODS_COUNT = sizeof(JNI_METHODS) / sizeof(JNI_METHODS[0]);
生成的c/c++jni函数定义为:
public final static native void SColor_setRed(long jarg1, SColor jarg1_, long jarg2);
SWIGEXPORT void JNICALL Java_net_sf_jirr_JirrJNI_SColor_1setRed(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2)
#define SET_A_JNI_METHOD(name, signature, func_ptr) \
{ (char*)#name, (char*)signature, (void*)func_ptr }
const char* JNI_REG_CLASS = "net/sf/jirr/JirrJNI";
JNINativeMethod JNI_METHODS[] = { SET_A_JNI_METHOD(SColor_setRed, "(JLnet/sf/jirr/SColor;J)V", Java_net_sf_jirr_JirrJNI_SColor_1setRed), ......};
int JNI_METHODS_COUNT = sizeof(JNI_METHODS) / sizeof(JNI_METHODS[0]);
由于c/c++jni函数不符合android c/c++jni函数调用约定(在这种情况下,生成的c/c++jni函数名应为Java_net_sf_jirr_JirrJNI_SColor_,如果需要在jni_OnLoad函数中注册本机函数的情况下调用,则应设置为Java_net_sf_jirr_JirrJNI_SColor_)
因此,我尝试手动注册本机方法,如下所示:
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
......
if (!registerNativeMethods(env, JNI_REG_CLASS, (JNINativeMethod*)JNI_METHODS, JNI_METHODS_COUNT)) {
return -1;
}
/* success -- return valid version number */
result = JNI_VERSION_1_4;
return result;
}
其中,JNI_REG_类、JNI_方法、JNI_方法计数定义为:
public final static native void SColor_setRed(long jarg1, SColor jarg1_, long jarg2);
SWIGEXPORT void JNICALL Java_net_sf_jirr_JirrJNI_SColor_1setRed(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2)
#define SET_A_JNI_METHOD(name, signature, func_ptr) \
{ (char*)#name, (char*)signature, (void*)func_ptr }
const char* JNI_REG_CLASS = "net/sf/jirr/JirrJNI";
JNINativeMethod JNI_METHODS[] = { SET_A_JNI_METHOD(SColor_setRed, "(JLnet/sf/jirr/SColor;J)V", Java_net_sf_jirr_JirrJNI_SColor_1setRed), ......};
int JNI_METHODS_COUNT = sizeof(JNI_METHODS) / sizeof(JNI_METHODS[0]);
因此,我需要解析net.sf.jirr.JirrJNI类,并为所有java本机方法生成一组SET_a_JNI_METHOD(……)宏
在这个SET_A_JNI_METHOD宏中,名称部分只是java本机函数名;签名部分符合java jni方法签名标准(在官方java jni参考中解释);func_ptr部分是添加Java_$(PackageName)u作为前缀,为Java本机方法名的每个部分(不包括类名部分)添加一些索引号(此处用“u”分隔)。
i、 e:
有没有关于如何使用Python正则表达式完成此操作的提示?这里有一些解决此问题的总体解决方案。它只是起作用了
#!/usr/bin/env python
#import the necessary modules.
import re #for regular expressions.
import sys #for parsing command line opts.
JNI_CPP_FUNC_PREFIX_INDEX = 1
JNI_METHOD_SIGNATURE_MAP = {
#basic type
'void':'V',
'boolean':'Z',
'int':'I',
'long':'J',
'double':'D',
'float':'F',
'byte':'B',
'char':'C',
'short':'S',
#array type
'int[]':'[I',
'float[]':'[F',
'byte[]':'[B',
'char[]':'[C',
'short[]':'[S',
'double[]':'[D',
'long[]':'[J',
'boolean[]':'[Z',
}
#param type = True; return type = False
def generateJniMethodTypeSignature(type, paramORreturnType = True):
retParamSignature = None
if type and type > "":
try:
retParamSignature = JNI_METHOD_SIGNATURE_MAP[type]
except:
if type == "String" :
retParamSignature = 'LJava/lang/String'
else :
retParamSignature = "Lnet/sf/jirr/" + type
#if paramORreturnType :
retParamSignature += ";"
#print "retParamSignature: "
#print retParamSignature
return retParamSignature
#if sys.argv[1]:
# print "File: %s" % (sys.argv[1])
# logfile = raw_input("Please input a log file to parse, e.g /var/file: ");
try:
jniMethodsFilePath = sys.argv[1]
jniMethodsFile = open(jniMethodsFilePath, "r")
outputFilePath = sys.argv[2]
outputFile = open(outputFilePath, "w")
for eachLine in jniMethodsFile.readlines() :
eachLine = eachLine.strip()
#print(eachLine)
# retType name space ( param space )
regex = re.match('^public\sfinal\sstatic\snative\s(\w+)\s(\w+)(\s)*(\()([^)]*)(\s)*(\))', eachLine)
if regex:
#'''
print "whole match: " + regex.group(0) #whole match.
'''
print "retType: " + regex.group(1) #retType
print "name: " + regex.group(2) #name
print "left space: "
print regex.group(3) #left space
print "(: " + regex.group(4) #(
print "param: " + regex.group(5) #param
print "right space: "
print regex.group(6) #right space
print "): " + regex.group(7) #)
#print eachLine
'''
retType = regex.group(1).strip()
funcName = regex.group(2).strip()
param = regex.group(5).strip()
#java native function name
command = "SET_A_JNI_METHOD(" + funcName + ", \"("
#print "param: " + regex.group(5)
paramRegex = re.split('\s*,\s*', param)
if paramRegex:
for eachParam in paramRegex:
eachParam = eachParam.strip()
#print "eachParam: " + eachParam
eachParamRegex = re.split('\s*', eachParam)
if eachParamRegex:
eachParamType = eachParamRegex[0].strip()
#print "eachParamType: " + eachParamType
paramTypeSignature = generateJniMethodTypeSignature(eachParamType)
if paramTypeSignature:
#print "paramTypeSignature: " + paramTypeSignature
command = command + paramTypeSignature
command = command + ")"
retTypeSignature = generateJniMethodTypeSignature(retType, False)
if retTypeSignature:
#parameter type signature.
command = command + retTypeSignature + "\", "
#print "command: " + command
#c/c++ jni function name
funcNameRegex = re.split('_', funcName)
if funcNameRegex:
#print cppFuncNameRegex
i = 0
cppFuncName = "Java_net_sf_jirr_JirrJNI_"
for eachFuncNamePart in funcNameRegex:
#print eachFuncNamePart
i = i + 1
if i == 1:
cppFuncName = cppFuncName + eachFuncNamePart
if i != len(funcNameRegex):
cppFuncName = cppFuncName + '_'
continue
cppFuncName = cppFuncName + str(JNI_CPP_FUNC_PREFIX_INDEX) + eachFuncNamePart
if i != len(funcNameRegex) :
cppFuncName = cppFuncName + '_'
command = command + cppFuncName + "), "
print "output: " + command + "\n"
outputFile.write(command + '\n')
outputFile.close()
jniMethodsFile.close()
except IOError, (errno, strerror):
print "I/O Error(%s) : %s" % (errno, strerror)
为了更好地理解你的问题,我对你的问题做了一些整理,我认为我们还有很多需要知道的。我认为您希望从Java函数声明和类名生成
SET\u A\u JNI\u方法
行,但我无法确切地看到签名或函数ptr是如何派生的(尤其是SColor\u 1setRed
部分)。请概括地描述一下你所说的,我也不明白。SWIG应该为您处理所有这些问题,在C++和java方面都生成包装功能。我用更详细的信息编辑了我的问题。