Share: Passing parameters between pascal and android ... lazarus / 43-Android ---------------------------------------------------------------------- tigerA15 · 2014-04-15 08:33 Hi, everybody, I wrote some sample that show how to passing parameters between pascal and android . (my english is very pool ) jniutil.pas includes these functions: Code: [Select]function JNI_JStringToString(Env: pJNIEnv; JStr: JString): string; cdecl; function JNI_StringToJString(Env: pJNIEnv; Str: string): jstring; cdecl; function JNI_JStringArrayToStrings(Env: PJNIEnv; jStrings: jarray): TStringDynArray;cdecl; function JNI_StringsToJStringArray(Env: PJNIEnv; strings: TStringDynArray): jarray;cdecl; function JNI_IntegersToJIntArray(Env: PJNIEnv; arr: TIntegerDynArray): JIntArray;cdecl; function JNI_JIntArrayToIntegers(Env: PJNIEnv; jarr: jintArray): TIntegerDynArray;cdecl; procedure JNI_ThrowException(Env: PJNIEnv; E: Exception);cdecl; function JNI_BytesToJByteArray(Env: PJNIEnv; Bytes: TByteDynArray): JByteArray;cdecl; function JNI_JByteArrayToBytes(Env: PJNIEnv; JBytes: jbyteArray): TByteDynArray;cdecl; //function PassString(Env: pJNIEnv; this: JObject; JStr: JString): JString; cdecl; procedure SetAndroidPackageName(Env: pJNIEnv; this: JObject;   PackageName: JString); cdecl; jniutil.pas: Code: [Select]unit jniutil; {********************************************************************* **********     JniUtil Unit by lrh (rock33@126.com)     非常感谢fpc和lazarus的各位大神无私奉献,让 pascal语言能同行各平台(包括现在     流行的android),谢谢猫工、delphicn的引路,也谢谢台湾的chenyuchih给启蒙。     小弟化了一天半的时间作了如下最常用的数据类型转换function,希望能帮助大家。     free pascal虽然偏冷,但并不代表她不优秀,要发扬光大得靠大家努力^_^。  ********************************************************************* **********} {$mode objfpc}{$H+} interface uses   SysUtils, jni, types, log; var   LibPath: string; type   TStringDynArray = array of string; function JNI_JStringToString(Env: pJNIEnv; JStr: JString): string; cdecl; function JNI_StringToJString(Env: pJNIEnv; Str: string): jstring; cdecl; function JNI_JStringArrayToStrings(Env: PJNIEnv; jStrings: jarray): TStringDynArray;cdecl; function JNI_StringsToJStringArray(Env: PJNIEnv; strings: TStringDynArray): jarray;cdecl; function JNI_IntegersToJIntArray(Env: PJNIEnv; arr: TIntegerDynArray): JIntArray;cdecl; function JNI_JIntArrayToIntegers(Env: PJNIEnv; jarr: jintArray): TIntegerDynArray;cdecl; procedure JNI_ThrowException(Env: PJNIEnv; E: Exception);cdecl; function JNI_BytesToJByteArray(Env: PJNIEnv; Bytes: TByteDynArray): JByteArray;cdecl; function JNI_JByteArrayToBytes(Env: PJNIEnv; JBytes: jbyteArray): TByteDynArray;cdecl; //function PassString(Env: pJNIEnv; this: JObject; JStr: JString): JString; cdecl; //字串傳遞範例 procedure SetAndroidPackageName(Env: pJNIEnv; this: JObject;   PackageName: JString); cdecl; implementation function JNI_JIntArrayToIntegers(Env: PJNIEnv; jarr: jintArray): TIntegerDynArray;cdecl; var   w_ret: TIntegerDynArray;   len: jint; begin   len := Env^^.GetArrayLength(Env, jarr);   SetLength(w_ret, len);   Env^^.GetIntArrayRegion(Env, jarr, 0, len, @w_ret[0]);   Result := w_ret; end; function JNI_IntegersToJIntArray(Env: PJNIEnv; arr: TIntegerDynArray): JIntArray;cdecl; var   len: cardinal;   intArray: JIntArray; begin   if (arr = nil) then   begin     Result := nil;     Exit;   end;   len := High(arr) + 1;   intArray := Env^^.NewIntArray(Env, Len);   Env^^.SetIntArrayRegion(Env, intArray, 0, len, @arr[0]);   Result := intArray; end; procedure JNI_ThrowException(Env: PJNIEnv; E: Exception);cdecl; var   jc: JObject; begin   jc := Env^^.FindClass(Env, 'java/lang/Exception');   Env^^.ThrowNew(Env, jc, PChar(E.Message)); end; { Convert byte array to JByteArray } function JNI_BytesToJByteArray(Env: PJNIEnv; Bytes: TByteDynArray): JByteArray;cdecl; var   len: cardinal;   byteArray: JByteArray; begin   if (bytes = nil) then   begin     Result := nil;     Exit;   end;   len := High(Bytes) + 1;   byteArray := Env^^.NewByteArray(Env, Len);   Env^^.SetByteArrayRegion(Env, byteArray, 0, len, @Bytes[0]);   Result := byteArray; end; function JNI_JByteArrayToBytes(Env: PJNIEnv; JBytes: jbyteArray): TByteDynArray;cdecl; var   len: jsize;   w_ret: TByteDynArray; begin   len := Env^^.GetArrayLength(env, JBytes);   SetLength(w_ret,len);   Env^^.GetByteArrayRegion(env, JBytes, 0, len, @w_ret[0]);   Result := w_ret; end; function JNI_JStringArrayToStrings(Env: PJNIEnv; jStrings: jarray): TStringDynArray;cdecl; var   len, i: jsize;   w_ret: TStringDynArray;   obj: jobject; begin   len := Env^^.GetArrayLength(env, jStrings);   SetLength(w_ret, len);   for i := 0 to len - 1 do   begin     obj := env^^.GetObjectArrayElement(env, jStrings, i);     w_ret[i] := JNI_JStringToString(Env, jString(obj));   end;   Result := w_ret; end; function JNI_StringsToJStringArray(Env: PJNIEnv; strings: TStringDynArray): jarray;cdecl; var   i, len: cardinal;   w_ret: jarray; begin   len := length(strings);   w_ret := Env^^.NewObjectArray(Env, Len,Env^^.FindClass(Env,'java/lan g/String'),JNI_StringToJString(Env,''));   for i := 0 to len - 1 do   begin     Env^^.SetObjectArrayElement(Env, w_ret, i, JNI_StringToJString(env, strings[i]));   end;   Result := w_ret; end; function JNI_StringToJString(Env: pJNIEnv; Str: string): jstring; cdecl; begin   Result := Env^^.NewStringUTF(Env, @Str[1]); //依Pascal String內容建立新的Java String回傳 end; function JNI_JStringToString(Env: pJNIEnv; JStr: JString): string; cdecl;   //Java String轉Pascal String副本範例 var   pAnsiCharTMP: pAnsiChar;   IsCopy: JBoolean;   pIsCopy: pJBoolean; begin   IsCopy := JNI_TRUE;   pIsCopy := @IsCopy;   if (JStr = nil) then   begin     Result := '';     Exit;   end;   pAnsiCharTMP := Env^^.GetStringUTFChars(Env, JStr, pIsCopy);   //將輸入的Java String轉為pAnsiChar(相容C語言的零位元終止字元陣列指標),因後續有釋放資源的動作故不宜在外加掛一層 StrPas()直接轉換成Pascal String。   if (pAnsiCharTMP = nil) then   begin     Result := '';   end   else   begin     Result := StrPas(pAnsiCharTMP); //將pAnsiChar轉為Pascal String後作為回傳值     Env^^.ReleaseStringUTFChars(Env, JStr, pAnsiCharTMP);     //輸入字串相關的轉換資源用完要釋放,否則會產生記憶體洩漏問題!   end; end; //-------------------------------------------------------------------- ---------- procedure SetAndroidPackageName(Env: pJNIEnv; this: JObject;   PackageName: JString); cdecl; begin   LibPath := '/data/data/' + JNI_JStringToString(Env, PackageName) + '/lib/'; end; end. project source: Code: [Select]library jni_demo3; {$mode objfpc}{$H+} {********************************************************************* **********     jni_demo3 by lrh (rock33@126.com)     非常感谢fpc和lazarus的各位大神无私奉献,让 pascal语言能同行各平台(包括现在     流行的android),谢谢猫工、delphicn的引路,也谢谢台湾的chenyuchih给启蒙。     小弟化了一天半的时间作了如下最常用的数据类型转换function,希望能帮助大家。     free pascal虽然偏冷,但并不代表她不优秀,要发扬光大得靠大家努力^_^。     main project source 只是简单带出这几个function的一些应用示例,具体如何调用还要     看android那边的java代码。  ********************************************************************* **********} uses   Classes, jniutil,types,sysutils,log,   jni in '../jni.pas'; function JNI_OnLoad(vm: PJavaVM; reserved: pointer): jint; cdecl; begin   Result := JNI_VERSION_1_6; end; procedure JNI_OnUnload(vm:PJavaVM;reserved:pointer); cdecl; begin end; function TestAddint(env: pJniEnv; this: jObject; a, b: jInt): jInt; cdecl; begin   LOGW(pchar('a='+inttostr(a)+',b='+inttostr(b)));   result:=a+b; end; function testSubfloat(env: pJniEnv; this: jObject; a, b: jdouble): jdouble; cdecl; begin   LOGW(pchar('a='+FloatToStr(a)+',b='+FloatToStr(b)));   result:=a-b; end; function testString(env: pJniEnv; this: jObject; str:jstring): jstring; cdecl; begin    result:=JNI_StringToJString(env,'hello,'+JNI_JStringToString(env,st r)+'.\n你好,'+JNI_JStringToString(env,str)); end; function testByteArray(env: pJniEnv; this: jObject; jbytes:jbyteArray): jbyteArray; cdecl; var w_vals:TByteDynArray; begin    LOGW('entry.');    w_vals:=JNI_JByteArrayToBytes(env,jbytes);    LOGW(pchar('length(w_vals):'+inttostr(length(w_vals))));    if length(w_vals)>=3 then begin      w_vals[0]:=w_vals[0]+1;      w_vals[1]:=w_vals[1]+1;      w_vals[2]:=w_vals[2]+1;    end;    result:=JNI_BytesToJByteArray(env,w_vals); end; function testIntegerArray(env: pJniEnv; this: jObject; jIntegers:jintArray): jintArray; cdecl; var w_vals:TIntegerDynArray; begin    w_vals:=JNI_JIntArrayToIntegers(env,jIntegers);    if length(w_vals)>=3 then begin      w_vals[0]:=w_vals[0]+1;      w_vals[1]:=w_vals[1]+1;      w_vals[2]:=w_vals[2]+1;    end;    result:=JNI_IntegersToJIntArray(env,w_vals); end; function testStringArray(env: pJniEnv; this: jObject; jstrs:jarray): jarray; cdecl; var w_vals:jniutil.TStringDynArray; begin    w_vals:=JNI_JStringArrayToStrings(env,jstrs);    if length(w_vals)>=3 then begin      w_vals[0]:='第一行:'+w_vals[0];      w_vals[1]:='第二行:'+w_vals[1];      w_vals[2]:='第三行:'+w_vals[2];    end;    result:=JNI_StringsToJStringArray(env,w_vals); end; procedure testThrowException(env: pJniEnv; this: jObject; message:jstring); cdecl; begin   JNI_ThrowException(env,Exception.Create(JNI_JStringToString(env,mess age))); end; exports   testAddint name 'Java_jnidemo_JniDemo_testAddint',   testSubfloat name 'Java_jnidemo_JniDemo_testSubfloat',   testString name 'Java_jnidemo_JniDemo_testString',   testByteArray name 'Java_jnidemo_JniDemo_testByteArray',   testIntegerArray name 'Java_jnidemo_JniDemo_testIntegerArray',   testStringArray name 'Java_jnidemo_JniDemo_testStringArray',   testThrowException name 'Java_jnidemo_JniDemo_testThrowException',   JNI_OnLoad,   JNI_OnUnLoad;   //JNI函式命名原則:Java___<函式名稱> begin end. Android source: Code: [Select]package jnidemo; public class JniDemo { static{ System.loadLibrary("jni_demo3"); } public static native int testAddint(int a,int b); public static native double testSubfloat(double a,double b); public static native String testString(String str); public static native byte[] testByteArray(byte[] vals); public static native int[] testIntegerArray(int[] vals); public static native String[] testStringArray(String[] vals); public static native void testThrowException(String message); } how to call ? Code: [Select] public static class PlaceholderFragment extends Fragment { public PlaceholderFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); ((Button)rootView.findViewById(R.id.btn_int)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //整數傳遞 int a=123; int b=234; int c=JniDemo.testAddint(a, b); Toast.makeText(_this, a+"+"+b+"="+c, Toast.LENGTH_SHORT).show(); } }); ((Button)rootView.findViewById(R.id.btn_float)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { double a=1.2345; double b=0.2045; double c=JniDemo.testSubfloat(a, b); Toast.makeText(_this, a+"+"+b+"="+c, Toast.LENGTH_SHORT).show(); } }); ((Button)rootView.findViewById(R.id.btn_strin g)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //string的互相傳遞,繁簡中文沒問題 String w_ret=JniDemo.testString("rock(陳大文)"); Toast.makeText(_this, w_ret, Toast.LENGTH_SHORT).show(); } }); ((Button)rootView.findViewById(R.id.btn_bytes)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { byte[] w_val=new byte[3]; w_val[0]=1; w_val[1]=2; w_val[2]=3; w_val=JniDemo.testByteArray(w_val); Toast.makeText(_this, String.format("[0]=%d, [1]=%d,[2]=%d",w_val[0],w_val[1],w_val[2]), Toast.LENGTH_SHORT).show(); } }); ((Button)rootView.findViewById(R.id.btn_integ ers)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int[] w_val=new int[3]; w_val[0]=10; w_val[1]=20; w_val[2]=30; w_val=JniDemo.testIntegerArray(w_val); Toast.makeText(_this, String.format("[0]=%d, [1]=%d,[2]=%d",w_val[0],w_val[1],w_val[2]), Toast.LENGTH_SHORT).show(); } }); ((Button)rootView.findViewById(R.id.btn_excep tion)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try{ JniDemo.testThrowException("這是一個異常!"); } catch (Exception e){ Toast.makeText(_this, e.getMessage(), Toast.LENGTH_SHORT).show(); } } }); ((Button)rootView.findViewById(R.id.btn_strin gs)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String[] w_val=new String[3]; w_val[0]="first(第一)"; w_val[1]="second(第二)"; w_val[2]="third(第三)"; w_val=JniDemo.testStringArray(w_val); Toast.makeText(_this, String.format("[0]=%s, [1]=%s,[2]=%s",w_val[0],w_val[1],w_val[2]), Toast.LENGTH_SHORT).show(); } }); return rootView; } } ---------------------------------------------------------------------- Seenkao · 2020-04-30 14:50 Большое спасибо! Долго мучался и состыковывал код паскаля и java, ваш код помог мне в этом! ---------------------------------------------------------------------- Otto · 2020-04-30 15:29 Hello Would it be possible for you to provide some more details about the project, such as e.g. version of the "LAMW" or other developed environment used? Thank you. ---------------------------------------------------------------------- Seenkao · 2020-04-30 16:43 Извиняюсь за мой английский. What information can you provide? LAMW does not carry information on translating arrays from Java to Pascal and vice versa. If you have useful information on the theme, it would be helpful. ---------------------------------------------------------------------- Otto · 2020-05-02 08:23 Спасибо Seenkao. Thank you Seenkao for answering me. Quote from: Seenkao on April 30, 2020, 06:43:01 pmИзвиняюсь за мой английский. Don't worry about English, I'm not native English speakers either. Perhaps some more clarification will be needed, but this will not be a problem. Quote from: Seenkao on April 30, 2020, 06:43:01 pmLAMW does not carry information on translating arrays from Java to Pascal and vice versa. That's right, that's the problem. I am working on an application that requires, among other things, also a front end for Android; as soon as I have new information regarding the specific topic I will definitely let you know. My Android app will need the functionality described in this thread. I am considering making such an application using LAMW, for this reason I was asking you about the project. You can send me a PM (Personal Message), if you prefer. Good bye До свидания. ---------------------------------------------------------------------- jmpessoa · 2020-05-03 17:52 @Seenkao QuoteLAMW does not carry information on translating arrays from Java to Pascal and vice versa. how not? you can verify this on several LAMW components methods.... ---------------------------------------------------------------------- Seenkao · 2020-05-03 20:18 Вы можете проверить сами. Но мне надоело искать "иголку в стоге сена".  Я нашёл, но только передачу в одну сторону, а мне надо в обе. (и только для int). Извиняюсь что на русском, но это не несёт нужной кому информации. ---------------------------------------------------------------------- Otto · 2020-05-03 21:53 Hello Seenkao { Although it's not a problem for me, other Forum users would like you to also add a translation into the internationally language for the Forum (currently English). } Jmpessoa knows what he says, because he is the one who develops LAMW. I think, that if you could post an excerpt of your code, which would present the need for translating arrays, it could be useful. ---------------------------------------------------------------------- Seenkao · 2020-05-03 22:53 All the necessary information is in the post tigerA15. I was interested in the translation byte: pascal to java, java to pascal. tiger A15 information must be divided into parts. Благодарю за внимание.