Using the JNI and NDK functions, you can call the Android C function from Delphi. There is a lot of work to implement this, and it has been proposed to directly call NDK functions. To do this, I created a small example file to declare an external C function by the lines that I found in the Delphi source code. More specifically in <path to delphi>\source\rtl\android .
I created a very small test program to test the functionality of calling a C function directly from Delphi. All of the source code that you find below is what I am testing now.
unit DLL_external; interface const MIDI_Lib = '/usr/lib/libmiditest.so'; test_fun = 'test_1'; function test_1 (n: Integer): Integer; cdecl; external MIDI_Lib name test_fun; implementation initialization finalization end.
Initialization and finalization are necessary because other errors are related to the lack of an initialization and completion code. The calling class:
unit DLL_Test_Main; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls, DLL_external; //{$I Androidapi.inc} type TForm1 = class(TForm) Button_Load: TButton; Label1: TLabel; procedure Button_LoadClick (Sender: TObject); procedure FormCreate(Sender: TObject); public procedure call_external_function (value: Integer); end; // Class: TForm1 // var Form1: TForm1; implementation {$R *.fmx} procedure TForm1.FormCreate (Sender: TObject); begin Label1.Text := 'External function not called yet'; end; // FormCreate // procedure TForm1.Button_LoadClick (Sender: TObject); begin call_external_function (3); end; // Button_LoadClick // procedure TForm1.call_external_function (value: integer); var n: Int32; begin n := test_1 (value); Label1.Text := Format ('%d = test_1 (%d)', [n, value]); end; // call_external_function // end.
Together with the native miditest library. This was built using ndk-build . The resulting libmiditest.so library was copied to C:\Users\Public\Documents\RAD Studio\12.0\PlatformSDKs\android-ndk-r8e\platforms\android-14\arch-arm\usr\lib , since this is the place where Delphi has hosted its own libraries.
#include <jni.h> int test_1 (int n) // little test for callability { return n * n; }
When I do ndk-build , the libmiditest.so file is created in the libs\armeabi-v7a . I copied this file to <path to your ndk directory>\platforms\android-14\arch-arm\usr\lib . Since I had some binding errors at the beginning (wrong names and such stupid errors), I used readelf -AWs libmiditest.so to create a list of characters and the expected library architecture. The name test_1 was in the character list, as in the arm v7 architecture (I use Nexus 7 for testing). When I run the Delphi program, it immediately runs on Android: "Unfortunately, DLL_Test_Propject has stopped." Looking at adb output (see below), it is expected that the file libDLL_Test_Project.so is expected. I replaced libmiditest.so with the unit DLL_external with libDLL_Test_Project.so and copied /usr/lib/libmiditest.so to /usr/lib/libDLL_Test_Project.so . It did not help.
Does anyone understand why the application created by Delphi is trying to load its own library? And better: any suggestion, what should I call Android C-function through Delphi?
I/InputReader( 608): Reconfiguring input devices. changes=0x00000010 D/dalvikvm( 799): GC_FOR_ALLOC freed 2003K, 15% free 14582K/16964K, paused 29ms, total 29ms I/PCKeyboard( 799): Loaded dictionary, len=841005 I/HK/LatinKeyboardBaseView( 799): onMeasure width=1200 I/HK/LatinKeyboardBaseView( 799): onMeasure width=1200 D/Documents( 3358): Used cached roots for com.android.providers.downloads.documents D/Documents( 3358): Used cached roots for com.android.externalstorage.documents D/Documents( 3358): Used cached roots for com.android.providers.media.documents D/Documents( 3358): Used cached roots for com.google.android.apps.docs.storage D/Documents( 3358): Update found 7 roots in 28ms D/BackupManagerService( 608): Received broadcast Intent { act=android.intent.action.PACKAGE_ADDED dat=package:com.embarcadero.DLL_Test_Project flg=0x4000010 (has extras) } V/BackupManagerService( 608): addPackageParticipantsLocked:
Update 1
From the comments, I realized that code can be part of a larger system. This code is a small standalone program. The native code library is really as small as you see here.
Update 2
As Arioch'The indicates that when using static binding (or implicit loading in terms of Windows), the main program does not load when the library does not load. This explains the adb post mentioned above. So querstion: why is libmiditest.so not loading?