2016-09-19 8 views
1

こんにちは私はいくつかの操作を行うCを使ってAndroidクラスを作成しました。もちろん私のtestlib.soが構築され、(Cygwinを使用してNDKビルド)をコンパイルし、私のDelphiのプロジェクトを展開されているのDelphiはAndroid Jniラッパーからプロシージャを使用します

JNIEXPORT void Java_Test_Project_Decode(JNIEnv* env, jclass clazz,jbyteArray dataIn, jbyteArray dataOut) 
{ 
    jsize len = (*env)->GetArrayLength(env, dataIn); 
    LOGV("JNI call Decode test dataIn Size = %d",len); 

jbyte *pByteIn = (*env)->GetByteArrayElements(env, dataIn, 0); 
jbyte *pByteOut = (*env)->GetByteArrayElements(env, dataOut, 0); 


*pDataOut = *pDataIn; pDataIn++; pDataOut++; 


*pDataOut = *pDataIn; pDataIn++; pDataOut++; 
*pDataOut = *pDataIn; pDataIn++; pDataOut++; 

// some routines 
(*env)->ReleaseByteArrayElements(env, dataOut, pByteOut, 0); 
(*env)->ReleaseByteArrayElements(env, dataIn, pByteIn, 0); 

} 

(Delphiで単なるテスト用):これらの手順の中で は、私はこの1つを使用します。

そして、私のDelphi FireMonkeyのクライアントで、私はこのように、この手順を使用します。

もちろんの
Java_Test_Project_Decode:procedure(PEnv: PJNIEnv; Obj:JObject;dataIn:Pointer;DataOut:Pointer); cdecl; 

私は自分のライブラリをロードした後:

Procedure LoadMyLib(); 
begin 
FMyLib := LoadLibrary(PChar(LibFolder + LibTest)); 
    if FMyLib = 0 then 
    begin 
    Exit; 
    end 
    else 
      begin 
      Java_Test_Project_Decode:=GetProcAddress(FMyLib,'Java_Test_Project_Decode'); 

      if not assigned (Java_Test_Project_Decode) then 
       begin 
       Exit; // Java_Test_Project_Decode procedure not loaded 
       end else 
        begin 
        // OK Java_Test_Project_Decode procedure loaded 
        end; 
     end; 
end; 

その後、私は手順を使用します。

Procedure TestMyProcedure (ADataIn: pointer; ASize: integer); 
var 
ADataOut:Pointer; 
begin 
// ADataIn pointer is not empty 
Java_Test_Project_Decode(PEnv,Obj,ADataIn,ADataOut); 
end; 

ここでは例外が発生し、アプリがクラッシュします。

誰でもこの問題を解決する手助けができますか?

ありがとうございました。

更新: 次のように私はADataOutを排除することができます

JNIEXPORT void Java_Test_Project_Decode(JNIEnv* env, jclass clazz,jbyteArray dataIn) 
    { 
     jsize len = (*env)->GetArrayLength(env, dataIn); 
     LOGV("JNI call Decode test dataIn Size = %d",len); 

    jbyte *pByteIn = (*env)->GetByteArrayElements(env, dataIn, 0); 

    // some routines 
    (*env)->ReleaseByteArrayElements(env, dataIn, pByteIn, 0); 

    } 

と私のDelphiの宣言:

Java_Test_Project_Decode:procedure(PEnv: PJNIEnv; Obj:JObject;dataIn:Pointer); cdecl; 

Procedure TestMyProcedure (ADataIn: pointer; ASize: integer); 

    begin 
    // ADataIn pointer is not empty 
    Java_Test_Project_Decode(PEnv,Obj,ADataIn); 
    end; 

しかし、常に同じ例外やエラーで、私もちょうどしようとしたが入手する

jsize len = (*env)->GetArrayLength(env, dataIn); 
    LOGV("JNI call Decode test dataIn Size = %d",len); 

同じエラー。

+0

'TestMyProcedure()'の 'ADataOut'は初期化されていませんが、' Java_Test_Project_Decode() 'は初期化されていません。 'Java_Test_Project_Decode()'は、サイズが少なくとも2要素の有効な** Java **バイト配列へのポインタになるために、 'ADataIn'と' ADataOut'を必要とします。 –

+0

@RemyLebeau、私は、DelphiとJavaの両方のプロシージャで 'ADateOut'を削除できますが、同じ例外とエラーが発生しています。 'ADataIn'は空ではありません。 – randydom

+0

あなたの質問を編集して、更新されたコードを表示してください。 –

答えて

0

あなたのDelphiの宣言は、それが現在の3つのカウントにない基礎となるCの宣言、一致している必要がありますレミーはあなたがRTLユニットAndroidapiから(JObject JNIブリッジインターフェイスタイプを使用している指摘したように

  1. を。 JNIタイプjobjectに相当するタイプJNIObject(RTLユニットAndroidapi.Jni.pasから)の代わりに、Javaクラスjava.lang.jobjectをラップしたJNI.JavaTypes.pasファイル(JNI.JavaTypes.pas)が含まれています。しかし、これはほとんど無関係です...
  2. 基礎となるCメソッドはパラメータを使用して静的/クラスメソッドであることを暗示していますが、Delphiのインポート宣言ではjobject相当のものを使用しようとしています。代わりにタイプJNIClassのパラメータを宣言する必要があります。
  3. 基礎となるCメソッドはjbytearray JNIパラメータタイプを使用しますが、デル012宣言はタイプPointerを使用して行われます。その代わりにjbytearrayに相当するDelphiを使用する必要があります。これはJNIByteArrayです。

両側のすべての引数と呼び出し規約が直接一致する場合のみ、呼び出しは成功します。

若干関連した注記では、読者にどのようにそのことを知らせるのが有益なのかもしれない。ライブラリはDelphiプロジェクト内にデプロイされ、実行時にアクセスしたパスの表現ははっきりとは分かりません。

同様の実験を行うために、.soファイルがあり、assets \ internal \ deploymentフォルダにデプロイするDeployment Managerをセットアップしました。これは、TPath.Combine(TPath.GetDocumentsPath, LibName)を使用してAndroidアプリコードからライブラリファイルを参照できることを意味しました。

関連する問題