2016-09-19 5 views
1

안녕하세요, 저는 C를 사용하여 일부 작업을 수행하는 Android 클래스를 만들었습니다. 물론 내 testlib.so이 내장 (Cygwin에서 사용 NDK 빌드)를 컴파일하고 내 델파이 프로젝트를 배포의델피는 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로 바로 테스트) : 이러한 절차 중 나는이 하나를 사용하고 싶습니다.

그리고 내 델파이 Firemonkey 클라이언트에서

나는이 방법이 절차를 사용 : 내 라이브러리를로드 한 후 물론

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

가 :

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

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; 

가 그럼 난 절차를 사용

하지만 여기에서는 예외가 발생하고 앱이 다운됩니다.

누구든지 해결할 수 있습니까?

감사합니다.

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

    } 

을 내 델파이 선언 : 다음과 같이 나는 ADataOut을 제거 할 수 : 업데이트

같은 예외 오류와 함께 항상

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 원소 크기의 유효한 ** 자바 ** 바이트 배열을 가리키는 포인터 인'ADataIn'과'ADataOut'를 필요로합니다. –

+0

@RemyLebeau, 델파이와 자바 프로 시저 모두에서 'ADateOut'을 제거 할 수 있지만 여전히 동일한 예외와 오류가 발생합니다. 'ADataIn'이 비어 있지 않고 초기화되지 않았습니다. – randydom

+0

업데이트 된 코드를 표시하려면 질문을 편집하십시오. –

답변

0

귀하의 델파이 선언은 세 가지 카운트에 현재하지 않는 기본 C 선언을 일치해야합니다 : 레미으로

  1. 당신이 RTL 단위 Androidapi에서 JObject JNI 브리지 인터페이스 유형 (사용 지적했다. JNI 유형 jobject과 동일한 유형 인 JNIObject (RTL 유닛 Androidapi.Jni.pas에서) 대신 Java 클래스 java.lang.jobject을 감싸는 JNI.JavaTypes.pas (JNI.JavaTypes.pas)가 있습니다. 그러나 이것은 대부분 부적절합니다 ...
  2. 기본 C 메서드는 jclass 매개 변수를 사용하여 정적/클래스 메서드를 의미하지만 델파이 가져 오기 선언은 jobject 동등 물을 사용하여 불일치를 시도합니다. 대신 JNIClass 유형의 매개 변수를 선언해야합니다.
  3. 기본 C 메소드는 jbytearray JNI 매개 변수 유형을 사용하지만 델파이 선언은 Pointer 유형을 사용하여 선언됩니다. 대신 jbytearray에 해당하는 델파이 (JNIByteArray)를 사용해야합니다.

양측의 모든 인수와 호출 규칙이 직접 일치하는 경우에만 호출이 성공합니다.

약간 관련있는 메모에서 독자에게 방법을 알리면 도움이되었을 수 있습니다.따라서 라이브러리는 Delphi 프로젝트 내에 배포되었으며 런타임에서 액세스 할 때 사용한 경로 표현은 명확하지 않습니다.

비슷한 실험을 수행하기 위해 .so 파일을 사용하여 배치 관리자를 assets \ internal \ deployment 폴더에 배치하도록 설정했습니다. 이것은 결국 TPath.Combine(TPath.GetDocumentsPath, LibName)을 사용하여 Android 앱 코드에서 라이브러리 파일을 참조 할 수 있음을 의미했습니다.