2016-09-19 15 views
1

Здравствуйте, я создал класс Android, используя C, который выполняет некоторые операции. Среди этих процедур я хочу использовать это: (только для тестирования с Delphi)Delphi использует процедуру от обертки Jni Android

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

} 

конечно мой testlib.so построен и скомпилированный (NDK-сборки с использованием Cygwin) и развернутого с моим проектом Delphi.

И в моем клиенте 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; 

Но здесь я получаю исключение, и приложение падает.

Возможно, кто-нибудь поможет мне исправить это?

Так что спасибо.

Update: можно устранить 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

'ADataOut' в' TestMyProcedure() 'не инициализирован, но' Java_Test_Project_Decode() 'пытается получить к нему доступ и написать ему. 'Java_Test_Project_Decode()' требует, чтобы 'ADataIn' и' ADataOut' были указателями на допустимые ** байт-массивы Java ** размером не менее 2 элементов. –

+0

@RemyLebeau, я могу устранить «ADateOut» как в процедурах Delphi, так и в Java, но все равно получаю одинаковые исключения и ошибки. хотя 'ADataIn' не пуст и не инициализирован – randydom

+0

Измените свой вопрос, чтобы показать обновленный код. –

ответ

0

Ваша декларация Delphi должна соответствовать лежащей в основе декларации C, что она ток не делает по трем пунктам:

  1. Как Реми отметил, что Вы используете JObject JNI Bridge тип интерфейса (от блока RTL Androidapi. JNI.JavaTypes.pas), который завершает класс Java java.lang.jobject, а не тип JNIObject (из модуля RTL Androidapi.Jni.pas), что эквивалентно типу JNI jobject. Однако это в основном не имеет значения, поскольку ...
  2. В вашем базовом методе C используется параметр jclass, который подразумевает, что это метод static/class, но ваша декларация импорта Delphi пытается использовать эквивалент jobject, что дает несоответствие. Вместо этого он должен объявить параметр типа JNIClass.
  3. В вашем базовом методе C используется тип параметра JNI jbytearray, но ваша декларация Delphi выполняется с использованием типа Pointer. Вместо этого вы должны использовать эквивалент Delphi для jbytearray, который равен JNIByteArray.

Только в том случае, когда все аргументы и соглашения о вызовах с обеих сторон совпадают, вызов будет успешным.

В незначительной заметке, возможно, было полезно информировать читателей о том, как.поэтому библиотека была развернута в проекте Delphi и какое выражение пути вы использовали для доступа к нему во время выполнения, поскольку это может быть далеки от ясности.

Для того, чтобы выполнить аналогичный эксперимент, у меня был файл .so, который я установил диспетчер развертывания для развертывания в папке assets \ internal \ deployment. Это означало, что я мог бы использовать TPath.Combine(TPath.GetDocumentsPath, LibName) для ссылки на файл библиотеки из кода приложения Android.