2012-02-04 5 views
0

Irrlicht C/C++ 3D 엔진 용 네이티브 JNI 함수 인터페이스를 생성하기 위해 SWIG를 사용했으며, Java 프록시 클래스와 중간 C/C++ 파일을 구현했습니다. Java 프록시 클래스와 Irrlicht C/C++ 3d 엔진을 연결하는 Java 원시 함수.안드로이드 jni 메소드 자동화를위한 python regex 사용 서명 생성

모든 java 프록시 클래스는 net.sf.jirr 패키지 내에서 생성됩니다. 생성 된 Java 원시 메소드는 net.sf.jirr.JirrJNI 클래스에 정의됩니다.

SWIG에서 생성 된 c/C++ jni 함수의 이름이 기본 android jni 함수 호출 규칙을 준수하지 않으므로 이러한 Java 원시 메소드를 해당 C/C++ jni 함수에 수동으로 등록해야합니다. 생성 된 자바 네이티브 방법은 다음과 같이 정의된다 :

즉, 예를 들어 생성 된 자바 네이티브 방법 net.sf.jirr.JirrJNI.SColor_setRed 걸릴

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가없이 호출해야 할 경우 생성 된 C/C++ JNI 함수 이름 Java_net_sf_jirr_JirrJNI_SColor_setRed해야한다 (이 경우 안드로이드 C/C++ JNI 함수 호출 규칙을 준수하지 않는 기능 등록 .주는 JNI_OnLoad 함수 내 g 기본 기능) 그래서

, 나는 수동으로 같이 인 네이티브 메소드를 등록하기 위해 노력하고있어 :

다음 JNI_REG_CLASS, JNI_METHODS, JNI_METHODS_COUNT는 다음과 같이 정의된다
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; 
} 

#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 jni 메소드 서명 표준 (java jni JNINativeMethod 참조)에서 설명합니다. func_ptr 부분은 자바 네이티브 메소드 이름 (여기서 "_"로 구분됨)의 각 부분 (클래스 이름 부분 제외)에 접두어로 일부 색인 번호를 추가하여 Java _ $ (PackageName) _을 추가하는 것입니다. 즉 :

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 

이 파이썬 정규식으로 수행하는 방법에 대한 어떤 힌트?

+0

나는 당신의 질문을 좀 더 잘 이해할 수 있도록 정돈 해 두었고, 나는 아직도 많이 알 필요가 있다고 생각합니다. 자바 함수 선언과 클래스 이름에서'SET_A_JNI_METHOD' 라인을 생성하고 싶다고 생각합니다. 그러나 서명이나 func_ptr이 어떻게 파생되는지 정확하게 볼 수는 없습니다 (특히'SColor_1setRed' 부분). 일반적인 용어로 개미를 설명하십시오. – Borodin

+0

나는 그 중 하나를 이해하지 못한다. SWIG는이 모든 것을 C++과 Java 측면에서 래퍼 함수를 ​​생성하여 처리해야합니다. – Thomas

+0

자신을 잘 이해하지 못해 죄송합니다. 더 자세한 정보로 내 질문을 편집했습니다. – David

답변

1

이 문제의 해결책은 다음과 같습니다. 그냥 효과가있었습니다.

#!/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)