I'm developing a mobile app using C++ Builder Berlin 10.1 which use a Jar library to scan barcodes. With Java2OP, I obtained a Delphi Bridge File to use the functions of the Jar. I translated it to C++ and include it to my project with the associated Jar. Here are my files:
Delphi:
{*******************************************************}
{ }
{ CodeGear Delphi Runtime Library }
{ Copyright(c) 2014 Embarcadero Technologies, Inc. }
{ }
{*******************************************************}
unit Android.JNI.ATScanLib;
interface
uses
Androidapi.JNIBridge,
Androidapi.JNI.JavaTypes;
type
// ===== Forward declarations =====
JAsyncTask = interface;//android.os.AsyncTask
JAsyncTask_Status = interface;//android.os.AsyncTask$Status
JATScanLib = interface;//com.atid.lib.ATScanLib
JATScanLib_OnResponseListener = interface;//com.atid.lib.ATScanLib$OnResponseListener
JATScanLib_TagSequenceTask = interface;//com.atid.lib.ATScanLib$TagSequenceTask
JVoid = interface;//java.lang.Void
// ===== Interface declarations =====
JAsyncTaskClass = interface(JObjectClass)
['{73C141D6-F8D7-4FE4-BFA3-3441B6367189}']
{class} function _GetSERIAL_EXECUTOR: JExecutor;
{class} function _GetTHREAD_POOL_EXECUTOR: JExecutor;
{class} function init: JAsyncTask; cdecl;
{class} procedure execute(runnable: JRunnable); cdecl; overload;
{class} property SERIAL_EXECUTOR: JExecutor read _GetSERIAL_EXECUTOR;
{class} property THREAD_POOL_EXECUTOR: JExecutor read _GetTHREAD_POOL_EXECUTOR;
end;
[JavaSignature('android/os/AsyncTask')]
JAsyncTask = interface(JObject)
['{8BC49850-F199-4620-BCFF-ACDA1D69417A}']
function cancel(mayInterruptIfRunning: Boolean): Boolean; cdecl;
function &get: JObject; cdecl; overload;
function &get(timeout: Int64; unit_: JTimeUnit): JObject; cdecl; overload;
function getStatus: JAsyncTask_Status; cdecl;
function isCancelled: Boolean; cdecl;
end;
TJAsyncTask = class(TJavaGenericImport<JAsyncTaskClass, JAsyncTask>) end;
JAsyncTask_StatusClass = interface(JEnumClass)
['{16452E24-44D5-4E84-990E-3C1916FB372B}']
{class} function _GetFINISHED: JAsyncTask_Status;
{class} function _GetPENDING: JAsyncTask_Status;
{class} function _GetRUNNING: JAsyncTask_Status;
{class} function valueOf(name: JString): JAsyncTask_Status; cdecl;
{class} function values: TJavaObjectArray<JAsyncTask_Status>; cdecl;
{class} property FINISHED: JAsyncTask_Status read _GetFINISHED;
{class} property PENDING: JAsyncTask_Status read _GetPENDING;
{class} property RUNNING: JAsyncTask_Status read _GetRUNNING;
end;
[JavaSignature('android/os/AsyncTask$Status')]
JAsyncTask_Status = interface(JEnum)
['{96B0BCE7-1312-49B9-9F33-43541680B0E7}']
end;
TJAsyncTask_Status = class(TJavaGenericImport<JAsyncTask_StatusClass, JAsyncTask_Status>) end;
JATScanLibClass = interface(JObjectClass)
['{9A209D1D-07C6-4309-88AD-8A2EF359CF34}']
{class} function _GetREAD_ENCODING_ERROR: Integer;
{class} function _GetREAD_ERROR: Integer;
{class} function _GetREAD_OK: Integer;
{class} function _GetREAD_TIMEOUT: Integer;
{class} function init: JATScanLib; cdecl;
{class} property READ_ENCODING_ERROR: Integer read _GetREAD_ENCODING_ERROR;
{class} property READ_ERROR: Integer read _GetREAD_ERROR;
{class} property READ_OK: Integer read _GetREAD_OK;
{class} property READ_TIMEOUT: Integer read _GetREAD_TIMEOUT;
end;
[JavaSignature('com/atid/lib/ATScanLib')]
JATScanLib = interface(JObject)
['{74B37E9E-F88A-4EB0-AEDF-538A472223A0}']
function Read(P1: TJavaArray<Byte>): Integer; cdecl;
function getReadResults: JString; cdecl;
procedure init; cdecl;
procedure setEncoding(P1: JString); cdecl;
procedure setOnResponseListener(P1: JATScanLib_OnResponseListener); cdecl;
procedure start; cdecl;
procedure stop; cdecl;
end;
TJATScanLib = class(TJavaGenericImport<JATScanLibClass, JATScanLib>) end;
JATScanLib_OnResponseListenerClass = interface(IJavaClass)
['{654B87BA-B4EE-4102-85E9-9FDFF3C82BAA}']
end;
[JavaSignature('com/atid/lib/ATScanLib$OnResponseListener')]
JATScanLib_OnResponseListener = interface(IJavaInstance)
['{35AC182B-7684-47EA-9BA8-07B504F85943}']
procedure onResponse(P1: Integer); cdecl;
end;
TJATScanLib_OnResponseListener = class(TJavaGenericImport<JATScanLib_OnResponseListenerClass, JATScanLib_OnResponseListener>) end;
JATScanLib_TagSequenceTaskClass = interface(JAsyncTaskClass)
['{1CF84DF6-6115-4FB5-9967-B55E74A3155C}']
end;
[JavaSignature('com/atid/lib/ATScanLib$TagSequenceTask')]
JATScanLib_TagSequenceTask = interface(JAsyncTask)
['{B83D8A9F-C1C4-4023-B1D8-3D9ABFB1FD2C}']
end;
TJATScanLib_TagSequenceTask = class(TJavaGenericImport<JATScanLib_TagSequenceTaskClass, JATScanLib_TagSequenceTask>) end;
JVoidClass = interface(JObjectClass)
['{E5AB6B2B-2580-469B-BBF6-C226984DFEBE}']
{class} function _GetTYPE: Jlang_Class;
{class} property &TYPE: Jlang_Class read _GetTYPE;
end;
[JavaSignature('java/lang/Void')]
JVoid = interface(JObject)
['{013CC63A-938C-46BE-ACAC-BA854F2F6AC8}']
end;
TJVoid = class(TJavaGenericImport<JVoidClass, JVoid>) end;
implementation
procedure RegisterTypes;
begin
TRegTypes.RegisterType('Android.JNI.ATScanLib.JAsyncTask', TypeInfo(Android.JNI.ATScanLib.JAsyncTask));
TRegTypes.RegisterType('Android.JNI.ATScanLib.JAsyncTask_Status', TypeInfo(Android.JNI.ATScanLib.JAsyncTask_Status));
TRegTypes.RegisterType('Android.JNI.ATScanLib.JATScanLib', TypeInfo(Android.JNI.ATScanLib.JATScanLib));
TRegTypes.RegisterType('Android.JNI.ATScanLib.JATScanLib_OnResponseListener', TypeInfo(Android.JNI.ATScanLib.JATScanLib_OnResponseListener));
TRegTypes.RegisterType('Android.JNI.ATScanLib.JATScanLib_TagSequenceTask', TypeInfo(Android.JNI.ATScanLib.JATScanLib_TagSequenceTask));
TRegTypes.RegisterType('Android.JNI.ATScanLib.JVoid', TypeInfo(Android.JNI.ATScanLib.JVoid));
end;
initialization
RegisterTypes;
end.
C++:
#ifndef Android_JNI_ATScanLibH
#define Android_JNI_ATScanLibH
#pragma delphiheader begin
#pragma option push
#pragma option -w- // All warnings off
#pragma option -Vx // Zero-length empty class member
#pragma pack(push,8)
#include <Androidapi.JNIBridge.hpp>
#include <Androidapi.JNI.JavaTypes.hpp>
#include <System.hpp>
#include <SysInit.hpp>
namespace Android{
namespace Jni{
namespace Atscanlib{
__interface JAsyncTask;
typedef System::DelphiInterface<JAsyncTask> _di_JAsyncTask;
__interface JAsyncTaskClass;
typedef System::DelphiInterface<JAsyncTaskClass> _di_JAsyncTaskClass;
__interface JAsyncTask_Status;
typedef System::DelphiInterface<JAsyncTask_Status> _di_JAsyncTask_Status;
__interface JAsyncTask_StatusClass;
typedef System::DelphiInterface<JAsyncTask_StatusClass> _di_JAsyncTask_StatusClass;
__interface JATScanLib;
typedef System::DelphiInterface<JATScanLib> _di_JATScanLib;
__interface JATScanLibClass;
typedef System::DelphiInterface<JATScanLibClass> _di_JATScanLibClass;
__interface JATScanLib_OnResponseListener;
typedef System::DelphiInterface<JATScanLib_OnResponseListener> _di_JATScanLib_OnResponseListener;
__interface JATScanLib_OnResponseListenerClass;
typedef System::DelphiInterface<JATScanLib_OnResponseListenerClass> _di_JATScanLib_OnResponseListenerClass;
__interface JATScanLib_TagSequenceTask;
typedef System::DelphiInterface<JATScanLib_TagSequenceTask> _di_JATScanLib_TagSequenceTask;
__interface JATScanLib_TagSequenceTaskClass;
typedef System::DelphiInterface<JATScanLib_TagSequenceTask> _di_JATScanLib_TagSequenceTaskClass;
__interface JVoid;
typedef System::DelphiInterface<JVoid> _di_JVoid;
__interface JVoidClass;
typedef System::DelphiInterface<JVoid> _di_JVoidClass;
__interface INTERFACE_UUID("{73C141D6-F8D7-4FE4-BFA3-3441B6367189}") JAsyncTaskClass : public Androidapi::Jni::Javatypes::JObjectClass
{
public:
virtual JExecutor _GetSERIAL_EXECUTOR() = 0;
virtual JExecutor _GetTHREAD_POOL_EXECUTOR() = 0;
HIDESBASE virtual _di_JAsyncTask __cdecl init() = 0;
virtual void __cdecl execute(JRunnable runnable) = 0;
__property JExecutor SERIAL_EXECUTOR = {read = _GetSERIAL_EXECUTOR};
__property JExecutor THREAD_POOL_EXECUTOR = {read = _GetTHREAD_POOL_EXECUTOR};
};
__interface INTERFACE_UUID("{73C141D6-F8D7-4FE4-BFA3-3441B6367189}") JAsyncTask : public Androidapi::Jni::Javatypes::JObject
{
public:
virtual bool __cdecl cancel(bool mayInterruptIfRunning) = 0;
virtual JObject __cdecl get() = 0;
virtual JObject __cdecl get(__int64 timeout, JTimeUnit unit_) = 0;
virtual _di_JAsyncTask_Status __cdecl getStatus() = 0;
virtual bool __cdecl isCancelled() = 0;
};
#pragma pack(push,4)
class PASCALIMPLEMENTATION TJAsyncTask : public Androidapi::Jnibridge::TJavaGenericImport__2<_di_JAsyncTaskClass, _di_JAsyncTask>{
typedef Androidapi::Jnibridge::TJavaGenericImport__2<_di_JAsyncTaskClass, _di_JAsyncTask> inherited;
public:
inline __fastcall TJAsyncTask(void) : Androidapi::Jnibridge::TJavaGenericImport__2<_di_JAsyncTaskClass, _di_JAsyncTask> (){}
inline __fastcall virtual ~TJAsyncTask(void){}
};
#pragma pack(pop)
__interface INTERFACE_UUID("{16452E24-44D5-4E84-990E-3C1916FB372B}") JAsyncTask_StatusClass : public Androidapi::Jni::Javatypes::JEnumClass
{
public:
virtual _di_JAsyncTask_Status _GetFINISHED() = 0;
virtual _di_JAsyncTask_Status _GetPENDING() = 0;
virtual _di_JAsyncTask_Status _GetRUNNING() = 0;
virtual _di_JAsyncTask_Status __cdecl valueOf(JString name) = 0;
virtual TJavaObjectArray__1<_di_JAsyncTask_Status> __cdecl values() = 0;
__property _di_JAsyncTask_Status FINISHED = {read = _GetFINISHED};
__property _di_JAsyncTask_Status PENDING = {read = _GetPENDING};
__property _di_JAsyncTask_Status RUNNING = {read = _GetRUNNING};
};
__interface INTERFACE_UUID("{96B0BCE7-1312-49B9-9F33-43541680B0E7}") JAsyncTask_Status : public Androidapi::Jni::Javatypes::JEnum
{
};
#pragma pack(push,4)
class PASCALIMPLEMENTATION TJAsyncTask_Status : public Androidapi::Jnibridge::TJavaGenericImport__2<_di_JAsyncTask_StatusClass, _di_JAsyncTask_Status>{
typedef Androidapi::Jnibridge::TJavaGenericImport__2<_di_JAsyncTask_StatusClass, _di_JAsyncTask_Status> inherited;
public:
inline __fastcall TJAsyncTask_Status(void) : Androidapi::Jnibridge::TJavaGenericImport__2<_di_JAsyncTask_StatusClass, _di_JAsyncTask_Status> (){}
inline __fastcall virtual ~TJAsyncTask_Status(void){}
};
#pragma pack(pop)
__interface INTERFACE_UUID("{9A209D1D-07C6-4309-88AD-8A2EF359CF34}") JATScanLibClass : public Androidapi::Jni::Javatypes::JObjectClass
{
public:
virtual int _GetREAD_ENCODING_ERROR() = 0;
virtual int _GetREAD_ERROR() = 0;
virtual int _GetREAD_OK() = 0;
virtual int _GetREAD_TIMEOUT() = 0;
HIDESBASE virtual _di_JATScanLib __cdecl init() = 0;
__property int READ_ENCODING_ERROR = {read = _GetREAD_ENCODING_ERROR};
__property int READ_ERROR = {read = _GetREAD_ERROR};
__property int READ_OK = {read = _GetREAD_OK};
__property int READ_TIMEOUT = {read = _GetREAD_TIMEOUT};
};
__interface INTERFACE_UUID("{74B37E9E-F88A-4EB0-AEDF-538A472223A0}") JATScanLib : public Androidapi::Jni::Javatypes::JObject
{
public:
virtual int __cdecl Read(TJavaArray__1<Byte> P1) = 0;
virtual JString __cdecl getReadResults() = 0;
virtual void __cdecl init() = 0;
virtual void __cdecl setEncoding(JString P1) = 0;
virtual void __cdecl setOnResponseListener(_di_JATScanLib_OnResponseListener P1) = 0;
virtual void __cdecl start() = 0;
virtual void __cdecl stop() = 0;
};
#pragma pack(push,4)
class PASCALIMPLEMENTATION TJATScanLib : public Androidapi::Jnibridge::TJavaGenericImport__2<_di_JATScanLibClass, _di_JATScanLib>{
typedef Androidapi::Jnibridge::TJavaGenericImport__2<_di_JATScanLibClass, _di_JATScanLib> inherited;
public:
inline __fastcall TJATScanLib(void) : Androidapi::Jnibridge::TJavaGenericImport__2<_di_JATScanLibClass, _di_JATScanLib> (){}
inline __fastcall virtual ~TJATScanLib(void){}
};
#pragma pack(pop)
__interface INTERFACE_UUID("{654B87BA-B4EE-4102-85E9-9FDFF3C82BAA}") JATScanLib_OnResponseListenerClass : public Androidapi::Jnibridge::IJavaClass
{
};
__interface INTERFACE_UUID("{35AC182B-7684-47EA-9BA8-07B504F85943}") JATScanLib_OnResponseListener : public Androidapi::Jnibridge::IJavaInstance
{
public:
virtual void __cdecl onResponse(int P1) = 0;
};
#pragma pack(push,4)
class PASCALIMPLEMENTATION TJATScanLib_OnResponseListener : public Androidapi::Jnibridge::TJavaGenericImport__2<_di_JATScanLib_OnResponseListenerClass, _di_JATScanLib_OnResponseListener>{
typedef Androidapi::Jnibridge::TJavaGenericImport__2<_di_JATScanLib_OnResponseListenerClass, _di_JATScanLib_OnResponseListener> inherited;
public:
inline __fastcall TJATScanLib_OnResponseListener(void) : Androidapi::Jnibridge::TJavaGenericImport__2<_di_JATScanLib_OnResponseListenerClass, _di_JATScanLib_OnResponseListener> (){}
inline __fastcall virtual ~TJATScanLib_OnResponseListener(void){}
};
#pragma pack(pop)
__interface INTERFACE_UUID("{1CF84DF6-6115-4FB5-9967-B55E74A3155C}") JATScanLib_TagSequenceTaskClass : public _di_JAsyncTaskClass
{
};
__interface INTERFACE_UUID("{B83D8A9F-C1C4-4023-B1D8-3D9ABFB1FD2C}") JATScanLib_TagSequenceTask : public _di_JAsyncTask
{
};
#pragma pack(push,4)
class PASCALIMPLEMENTATION TJATScanLib_TagSequenceTask : public Androidapi::Jnibridge::TJavaGenericImport__2<_di_JATScanLib_TagSequenceTaskClass, _di_JATScanLib_TagSequenceTask>{
typedef Androidapi::Jnibridge::TJavaGenericImport__2<_di_JATScanLib_TagSequenceTaskClass, _di_JATScanLib_TagSequenceTask> inherited;
public:
inline __fastcall TJATScanLib_TagSequenceTask(void) : Androidapi::Jnibridge::TJavaGenericImport__2<_di_JATScanLib_TagSequenceTaskClass, _di_JATScanLib_TagSequenceTask> (){}
inline __fastcall virtual ~TJATScanLib_TagSequenceTask(void){}
};
#pragma pack(pop)
__interface INTERFACE_UUID("{E5AB6B2B-2580-469B-BBF6-C226984DFEBE}") JVoidClass : public Androidapi::Jni::Javatypes::JObjectClass
{
public:
virtual Jlang_Class _GetTYPE() = 0;
__property Jlang_Class TYPE = {read = _GetTYPE};
};
__interface INTERFACE_UUID("{013CC63A-938C-46BE-ACAC-BA854F2F6AC8}") JVoid : public Androidapi::Jni::Javatypes::JObject
{
};
#pragma pack(push,4)
class PASCALIMPLEMENTATION TJVoid : public Androidapi::Jnibridge::TJavaGenericImport__2<_di_JVoidClass, _di_JVoid>{
typedef Androidapi::Jnibridge::TJavaGenericImport__2<_di_JVoidClass, _di_JVoid> inherited;
public:
inline __fastcall TJVoid(void) : Androidapi::Jnibridge::TJavaGenericImport__2<_di_JVoidClass, _di_JVoid> (){}
inline __fastcall virtual ~TJVoid(void){}
};
#pragma pack(pop)
}
}
}
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_ANDROID_JNI_ATLIB)
using namespace Android::Jni::Atscanlib;
#endif
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_ANDROID_JNI)
using namespace Android::Jni;
#endif
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_ANDROID)
using namespace Android;
#endif
#pragma pack(pop)
#pragma option pop
#pragma delphiheader end.
#endif
When I tried to use the functions like this :
TJATScanLib* scan = new TJATScanLib();
_di_JATScanLibClass scanner = TJATScanLib::JavaClass->init();
C++ Builder raised this link error :
[ldandroid Erreur] C:\Users\Public\Documents\Embarcadero\Studio\18.0\CatalogRepository\AndroidNDK-9c_x86_GIB.Build.22858.6822\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\bin\arm-linux-androideabi-ld.exe: .\Android\Debug\Connexion.o: in function TForm_Connexion::TForm_Connexion(System::Classes::TComponent*):C:\Users\dylan\Documents\Embarcadero\Studio\Projets\PDA_Android/Connexion.cpp:28:error:
undefined reference to 'Androidapi::Jnibridge::TJavaGenericImport__2, System::DelphiInterface >::GetJavaClass()'
and
[ldandroid Erreur] C:\Users\Public\Documents\Embarcadero\Studio\18.0\CatalogRepository\AndroidNDK-9c_x86_GIB.Build.22858.6822\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\bin\arm-linux-androideabi-ld.exe: .\Android\Debug\Connexion.o: in function TForm_Connexion::TForm_Connexion(System::Classes::TComponent*):C:\Users\dylan\Documents\Embarcadero\Studio\Projets\PDA_Android/Connexion.cpp:30:error:
undefined reference to 'vtable for Android::Jni::Atscanlib::TJATScanLib'
Did I use the function in the wrong way?
.pas
files as-is in C++ projects. When a.pas
file is compiled in a C++ project, it will generate a suitable.hpp
file that you can then#include
in your C++ code. – Remy LebeauGetJavaClass()
error, that suggests you are not linking to the RTL package that implements the JNI bridge framework itself. – Remy Lebeau