使用 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 函数。
即以生成的java原生方法net.sf.jirr.JirrJNI.SColor_setRed为例: 生成的java本机方法定义为:
public final static native void SColor_setRed(long jarg1, SColor jarg1_, long jarg2);
生成的c/c++ jni函数定义为:
SWIGEXPORT void JNICALL Java_net_sf_jirr_JirrJNI_SColor_1setRed(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2)
由于c/c++ jni函数不符合android c/c++ jni函数调用约定(在本例中生成的c/c++ jni如果需要在 JNI_OnLoad 函数中注册本机函数的情况下调用函数,则函数名称应为 Java_net_sf_jirr_JirrJNI_SColor_setRed。)
因此,我尝试手动注册本机方法就像:
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_CLASS、JNI_METHODS、JNI_METHODS_COUNT 定义为:
#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 JNINativeMethod 参考); func_ptr 部分是添加 Java_$(PackageName)_ 作为前缀,为 java 原生方法名称的每个部分(不包括类名部分)添加一些索引号(这里用“_”分隔)。 即:
Java native method: IFileSystem_getFileDir
name part: IFileSystem_getFileDir;
func_ptr part: Java_net_sf_jirr_JirrJNI_IFileSystem_1getFileDir;
Java native method: IFileSystem_addFolderFileArchive__SWIG_0
name part: IFileSystem_addFolderFileArchive__SWIG_0;
func_ptr part: Java_net_sf_jirr_JirrJNI_IFileSystem_1addFolderFileArchive_1_1SWIG_10
关于如何使用 Python 正则表达式完成此操作有任何提示吗?
I used SWIG for generating some native JNI function interface for Irrlicht C/C++ 3D engine, and I got a bunch of java proxy classes and an intermediate c/c++ files which implements the java native functions to glue the java proxy classes and Irrlicht C/C++ 3d engine.
All java proxy classes are generated within the package net.sf.jirr. And the generated java native methods are defined in the net.sf.jirr.JirrJNI class.
Since the name of the SWIG generated c/c++ jni functions doesn't comply with the default android jni function call convention, I need to register these java native method with the corresponding C/C++ jni function manually.
i.e. Take the generated java native method net.sf.jirr.JirrJNI.SColor_setRed for example:
The generated java native method is defined as:
public final static native void SColor_setRed(long jarg1, SColor jarg1_, long jarg2);
The generated c/c++ jni function is defined as:
SWIGEXPORT void JNICALL Java_net_sf_jirr_JirrJNI_SColor_1setRed(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2)
As the c/c++ jni function doesn't comply with android c/c++ jni function call convention(in this case the generated c/c++ jni function name should be Java_net_sf_jirr_JirrJNI_SColor_setRed if it needs to be called without registering the native function within the JNI_OnLoad function.)
So, I'm trying to register the native methods manually which is like:
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;
}
where the JNI_REG_CLASS, JNI_METHODS, JNI_METHODS_COUNT are defined as:
#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]);
So, I need to parse the net.sf.jirr.JirrJNI class and generate a bunch of SET_A_JNI_METHOD(......) macroes for all of the java native methods.
In this SET_A_JNI_METHOD macro, the name part is just the java native function name; the signature part complies with the java jni method signature standards(which is explained in the official java jni JNINativeMethod reference); the func_ptr part is to add Java_$(PackageName)_ as the prefix add some index number to each part(excluding the class name part) of the java native method name(separated by "_" here).
i.e:
Java native method: IFileSystem_getFileDir
name part: IFileSystem_getFileDir;
func_ptr part: Java_net_sf_jirr_JirrJNI_IFileSystem_1getFileDir;
Java native method: IFileSystem_addFolderFileArchive__SWIG_0
name part: IFileSystem_addFolderFileArchive__SWIG_0;
func_ptr part: Java_net_sf_jirr_JirrJNI_IFileSystem_1addFolderFileArchive_1_1SWIG_10
Any hint on how to get this done with Python regex?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是这个问题的一些粗略的解决方案。它刚刚起作用了。
Here is some gross solution for this problem. It just worked.