![]() |
Android: .SO erstellen und benutzen
Hallo,
ich versuche gerade eine .SO für Android mit Delphi zu erstellen (10.4.2 oder neuer) und in einem Testprogramm zu benutzen. Dazu hab' ich ein Library Projekt erstellt mit einer flachen function drin. Die hat 2 Integer Parameter und einen Integer Rückgabewert (addiert das einfach nur). Beim Compilieren wird auch eine .SO Datei erzeugt. So wie es aussieht kann ich die jedoch nicht statisch einbinden (anders als eine DLL), weil da der Linker meckert. Also versuche ich das gerade mittels LoadLibrary einzubinden und ich habe die .SO auch im Deplyoment Manager schon hinzugefügt. Remote-Pfad ist library\lib\armeabi-v7a\ da ich das bisher mal noch kit 32 Bit zum Testen mache. Funktion ist cdecl von der Aufruf Konvention. Nur: zur Laufzeit stürzt die App beim Aufruf einfach ab. Ich prüfe aber den Rückgabewert von GetProcAddress auf Nil, das kann es also nicht sein. Logcat hab' ich noch nicht aufgezeichnet, da suche ich noch einen passenden Viewer für, da ja im Android SDK inzwischen keiner mehr drin ist, ich aber nicht ein komplettes Android Studio nu für den Viewer installieren möchte... Code zum Aufruf:
Delphi-Quellcode:
Hier der relevante Logcat Auszug:
unit GUIMain;
interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls, FMX.Edit, FMX.Controls.Presentation; type TDoAdd = function(a, b: Integer): Integer; cdecl; Tf_Main = class(TForm) Label1: TLabel; Label2: TLabel; tf_Summand1: TEdit; Label3: TLabel; l_Result: TLabel; tf_Summand2: TEdit; b_Calc: TButton; procedure b_CalcClick(Sender: TObject); private FDoAdd : TDoAdd; public end; var f_Main: Tf_Main; implementation uses System.IOUtils; {$R *.fmx} {$IFDEF WIN32} function DoAdd(a, b: Integer): Integer; cdecl; external 'SO_Test.dll'; {$ELSE} //function DoAdd(a, b: Integer): Integer; cdecl; external 'libSO_Test.so'; {$ENDIF} procedure Tf_Main.b_CalcClick(Sender: TObject); var Handle : HMODULE; begin Handle := LoadLibrary(PChar(TPath.Combine(TPath.GetLibraryPath, 'libSO_Test.so'))); if (Handle <> 0) then begin try FDoAdd := GetProcAddress(Handle, PChar('DoAdd')); if (@FDoAdd = nil) then l_Result.Text := 'Failure loading proc' else begin l_Result.Text := FDoAdd(tf_Summand1.Text.ToInteger, tf_Summand2.Text.ToInteger).ToString; FDoAdd := nil; end; finally FreeLibrary(Handle); end; end else l_Result.Text := 'SO handle is invalid' end; end.
Code:
Wer hat noch eine Idee?
10-20 13:36:28.234 31445 31445 W adero.SOTestGU: Accessing hidden method Landroid/view/MotionEvent;-><init>()V (greylist-max-o, JNI, denied): com.embarcadero.SOTestGUI
10-20 13:36:28.451 1513 2333 W InputDispatcher: channel 'a66b6a3 PopupWindow:efeb1b3 (server)' ~ Consumer closed input channel or an error occurred. events=0x9: system_server 10-20 13:36:28.451 1513 2333 E InputDispatcher: channel 'a66b6a3 PopupWindow:efeb1b3 (server)' ~ Channel is unrecoverably broken and will be disposed!: system_server 10-20 13:36:28.452 1513 2333 W InputDispatcher: channel '1179c6e com.embarcadero.SOTestGUI/com.embarcadero.firemonkey.FMXNativeActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9: system_server 10-20 13:36:28.452 1513 2333 E InputDispatcher: channel '1179c6e com.embarcadero.SOTestGUI/com.embarcadero.firemonkey.FMXNativeActivity (server)' ~ Channel is unrecoverably broken and will be disposed!: system_server 10-20 13:36:28.463 1513 3607 W InputDispatcher: Attempted to unregister already unregistered input channel 'a66b6a3 PopupWindow:efeb1b3 (server)': system_server 10-20 13:36:28.464 1513 6252 I am_proc_died: [0,31445,com.embarcadero.SOTestGUI,0,2]: system_server 10-20 13:36:28.466 700 700 I Zygote : Process 31445 exited cleanly (231) 10-20 13:36:28.472 1513 2359 W InputDispatcher: Attempted to unregister already unregistered input channel '1179c6e com.embarcadero.SOTestGUI/com.embarcadero.firemonkey.FMXNativeActivity (server)': system_server 10-20 13:36:28.486 1513 6252 I am_uid_stopped: 10310: system_server 10-20 13:36:28.488 1513 6252 I wm_finish_activity: [0,18028204,39,com.embarcadero.SOTestGUI/com.embarcadero.firemonkey.FMXNativeActivity,proc died without state saved]: system_server 10-20 13:36:28.492 1513 6252 I wm_task_removed: [39,removeChild: last r=ActivityRecord{11316ac u0 com.embarcadero.SOTestGUI/com.embarcadero.firemonkey.FMXNativeActivity t-1 f}} in t=Task{f2191ae #39 visible=false type=standard mode=fullscreen translucent=true A=10310:com.embarcadero.SOTestGUI U=0 StackId=39 sz=0}]: system_server 10-20 13:36:28.492 1513 6252 I wm_task_removed: [39,removeTask]: system_server 10-20 13:36:28.492 1513 6252 I wm_task_removed: [39,removeTask]: system_server 10-20 13:36:28.492 1513 6252 I wm_stack_removed: 39: system_server 10-20 13:36:28.496 1513 6252 I wm_set_resumed_activity: [0,com.google.android.packageinstaller/com.android.packageinstaller.DeleteStagedFileOnResult,resumeTopActivityInnerLocked]: system_server 10-20 13:36:28.497 1513 6252 D hmdEnterprise: <isUninstallPackage> blockUninstallpackage =false: system_server 10-20 13:36:28.500 1513 1775 I libprocessgroup: Successfully killed process cgroup uid 10310 pid 31445 in 36ms: system_server Die nächsten Versuche werde ich mit StdCall Aufrufkonvention und von 11.3 aus durchführen. Evtl. noch die .SO in einen anderen Pfad bereitstellen lassen? .\internal\assets vielleicht? |
AW: Android: .SO erstellen und benutzen
Hallo,
LoadLibrary, und WM_(Nachrichten) sind Windows spezifiesch und können nicht in ein Android Project verwendet werden. Du must Funktionen und Konstanten verwenden, die für Android unterstützt werden |
AW: Android: .SO erstellen und benutzen
Hallo,
deine Antwort mit LoadLibrary ist leider falsch! Wenn du dir mal System.SysUtils.pas anschaust, wirst du sehen, dass es dort sowohl ein LoadLibrary für Posix Plattformen gibt! Das ruft intern dlopen auf! Und von Windows Botschaftsn hab' ich gar nix geschrieben (ja, war von dir nur ein Beispiel). Grüße TurboMagic |
AW: Android: .SO erstellen und benutzen
Eine neue Erkenntnis (diesmal von D11.3):
Gebe ich mit TPath.GetLibraryPath in einen String aus: s := TPath.Combine(TPath.GetLibraryPath, 'libSO_Test.so'); Erhalte ich das: '/data/app/~~td-k7J_qLsGigGgnn9hKrw==/com.embarcadero.SOTestGUI-mFk3eeCSAweRM71VBK_lvw==/lib/arm/libSO_Test.so' Ich weiß aber nicht ob das korrekt ist und es sieht auch nicht unbeding so aus als würde es zum Remote Pfad library\lib\armeabi-v7a\ passen... Wie müsste ich den Remote Pfad ändern? Einfach in lib/arm/ ist wohl nicht richtig, da ich dann später beim Hinzufügen der 64 Bit .SO ein Problem bekomme... Grüße TurboMagic |
AW: Android: .SO erstellen und benutzen
mein altes SAMSUNG Android Galaxy hat die Möglichkeit, die Verzeichnis-Struktur anzeigen
zu lassen. |
AW: Android: .SO erstellen und benutzen
Hallo,
danke für den Tipp. Leider war ich da auch schon ;-) Nur ist das bei den neueren Geräte meist schreibgeschützt und nicht mal die Shell (adb shell) kann da überall rein bzw. zeigt Unterordner an. Aber: glücklicherweise gibt's ja System.SysUtils.FileExists und das sagt, dass es die betreffende .SO an dem Pfad wirklich gibt. Tja, nur warum crasht das dann beim LoadLibrary? :-( Grüße TurboMagic |
AW: Android: .SO erstellen und benutzen
könnte an die Rechte liegen - oder das falsche binär Format.
Mit den GNU C/C++ kannst Du für beliebige Systeme .EXE, .DLL, .SO schreiben. Allerdings hat jede Architektur und Chip ein Eigenes Format. z.B. ist es ein Unterschied, wenn man versucht ein 64 Bit Image auf einer 32 Bit Umgebung zu starten - das geht in der Regel nicht. Anders als auf einen 64 Bit System, dort können 32 Images gestartet werden. Dann liegst auch an den Endian / BigEndian. Oder Du hast Funktionen, die es in dem Image nicht gibt. Unter Windows in der MSYS2 Shell gibt es wie unter Linux ein Tool namens "ldd" - nicht an den "ld" Linker denken ! LDD prüft, welche Bibliotheken verwendet werden, und zeigt deren "einkompilierten" Pfade an. Wenn der Pfad nicht existiert, dann wird die Lade-Adresse 0 sein, und führt daher zu einen Lade-Fehler. |
AW: Android: .SO erstellen und benutzen
Zitat:
So wie im 64 Bit-Windows das 16 Bit-Subsystem entfernt wurde, weswegen man dort keine 16 Bit-DOS-Programme (*.com) mehr starten kann, kann man auch das 32 Bit SubSystem entfernen. (keine 32 Bit-DLLs und Programme des Windows installieren) -> dann könnte man zwar in der CPU noch 32 Bit-Code ausführen, aber wenn die 32 Bit-WinAPI fehlt, läuft dennoch fast nichts. Auch muß man in eine 64 Bit-CPU keine 32 Bit-Instruktionen einbauen (oder das OS verietet das Umschalten), womit dann garnichts mehr mit 32 Bit ginge. PS: Das Gegenteil davon macht Wine ... es stellt quasi einen Großteil der Win32-API bereit (vorwiegend als Umleitung auf die Linux-API/Funktionen), wordurch Windows-Programme dort laufen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:12 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz