我想在我的delphi android项目中使用本机c ++库; 这是我想从Delphi代码部分调用它的重要部分:
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "EmbJniTest"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
JavaVM* gJavaVM = NULL;
//------------------------------------------------------------------------
jint JNI_OnLoad(JavaVM* aVm, void* aReserved)
{
// cache java VM
gJavaVM = aVm;
JNIEnv* env;// latter on it'll be used as global var
LOGI("JVM INIT");
if (aVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK)
{
LOGI("Failed to get the environment");
return -1;
}
return JNI_VERSION_1_6;
}
这里是我的delphi代码部分加载mylibrary:
LIBNAME = 'libtest.so';
function try_load_dll:integer;
var libPath:system.string;
begin
_status:= 0 ;
libPath:=TPath.Combine(tpath.GetLibraryPath,libname);
_status := LoadLibrary(PChar(libPath));
result:=_Status;
if( _status= 0 )then exit;
end;
问题在于
JNI_OnLoad
永远不会被调用;我无法在logcat中看到任何关于它的日志。
我已经读过JNI_OnLoad的调用是由System.loadLibrary()完成的。如果 您没有使用它来加载库,JNI_OnLoad不会发生。
来自here的所以,无论如何,我可以从我的delphi代码中调用它。
谢谢
答案 0 :(得分:2)
只是想知道为什么
JNI_OnLoad
没有被调用
JNI_OnLoad()
通常由Java JVM调用,如果它是加载本机库的那个(即,当Java代码调用System.loadLibrary()
时)。
由于您的示例中并非如此,因此您的JNI_OnLoad()
未被调用。您自己直接加载图书馆,因此您必须自己致电JNI_OnLoad()
。
Embarcadero在TJNI_OnLoad
单元中声明Embarcadero.Jni
函数指针类型。使用GetProcAddress()
获取指向库的导出JNI_OnLoad()
函数的指针,并将该指针指定给TJNI_OnLoad
变量。然后你可以像任何其他功能一样调用JNI_OnLoad()
。
后者我将
JNIEnv* env
保存为全局变量,以便在我的原生lib中的某些过程和函数中使用它
JNI_OnLoad()
将JavaVM*
指针作为输入。调用JNI_OnLoad()
的人必须传入指向有效JavaVM
对象的指针。
Java JVM通常会为您处理。但是,由于您自己加载库,因此必须自己调用JNI_OnLoad()
,因此必须从Delphi代码中提供JavaVM
对象。您应该 能够使用Delphi的RTL内部使用的相同JNI_CreateJavaVM()
对象 - 而不是自己调用JavaVM
- JavaMachine
指针RTL的System
单元(仅将其强制转换为PJavaVM
,也在Embarcadero.Jni
单元中声明。)
试试这个:
uses
..., Embarcadero.Jni
const
LIBNAME = 'libtest.so';
function try_load_dll: THandle;
var
libPath: string;
OnLoadFunc: TJNI_OnLoad;
hlib: THandle;
begin
Result := 0;
libPath := TPath.Combine(TPath.GetLibraryPath, libname);
hlib := LoadLibrary(PChar(libPath));
if hlib = 0 then Exit;
@OnLoadFunc := GetProcAddress(hlib, 'JNI_OnLoad');
if not Assigned(OnLoadFunc) then
begin
FreeLibrary(hlib);
Exit;
end;
OnLoadFunc(PJavaVM(System.JavaMachine), nil);
Result := hlib;
end;