2012-02-04 7 views
0

Irrigicht C/C++ 3Dエンジン用のネイティブJNI関数インタフェースを生成するためにSWIGを使用しました。 JavaプロキシクラスとIrrlicht C/C++ 3dエンジンをグルーピングするためのJavaネイティブ関数Python正規表現を使用してAndroidのjniメソッドのシグネチャの生成を自動化

すべての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それはなしで呼び出される必要がある場合には、生成されたC/C++ JNI関数名がJava_net_sf_jirr_JirrJNI_SColor_setRedする必要があり、この場合には(アンドロイドC/C++ JNI関数呼び出し規則に準拠していない機能登録する。グラムネイティブ関数JNI_OnLoad関数内)

だから、私のようである手動でネイティブメソッドを登録しようとしている:

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; 
} 

したがって、net.sf.jirr.JirrJNIクラスを解析して、すべてのJavaネイティブメソッドのSET_A_JNI_METHOD(......)マクロを生成する必要があります。

このSET_A_JNI_METHODマクロでは、名前部分はJavaのネイティブ関数名です。署名部分はjava jniメソッドの署名標準(公式のjava jni JNINativeMethodリファレンスで説明されています)に準拠しています。 func_ptr部分は、Javaのネイティブメソッド名(ここでは "_"で区切られた)の各部分(クラス名部分を除く)にいくつかのインデックス番号を追加する接頭辞として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 

これはPythonの正規表現で行わ取得する方法上の任意のヒント?

+0

あなたの質問をちょっと整理して、それをよりよく理解するようにしました。私はまだ知りたいことがたくさんあると思います。私は、あなたは、Java関数宣言とクラス名から '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)