我有一个 native c++ 库,我想在我的 delphi android 项目中使用它; 这是我想从 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;
}
这是我加载 mylibrary 的 delphi 代码部分:
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 代码中调用它。
谢谢
最佳答案
Just wondering why
JNI_OnLoad
is not being invoked
JNI_OnLoad()
通常由 Java JVM 调用,如果它是加载 native 库的那个(即,当 Java 代码调用 System.loadLibrary()
时)。
因为在您的示例中不是这种情况,所以您的 JNI_OnLoad()
没有被调用。您自己直接加载库,因此您必须自己调用 JNI_OnLoad()
。
Embarcadero 在Embarcadero.Jni
单元中声明了一个TJNI_OnLoad
函数指针类型。使用 GetProcAddress()
获取指向库导出的 JNI_OnLoad()
函数的指针,并将该指针分配给 TJNI_OnLoad
变量。然后您可以像调用任何其他函数一样调用 JNI_OnLoad()
。
latter on i'll save
JNIEnv* env
as global variable to use it in some procedures and functions within my native lib
JNI_OnLoad()
将 JavaVM*
指针作为输入。调用 JNI_OnLoad()
的人必须传入一个指向有效 JavaVM
对象的指针。
Java JVM 通常会为您处理。但是,由于您是自己加载库,因此必须自己调用 JNI_OnLoad()
,因此您必须从 Delphi 代码中提供一个 JavaVM
对象。与其自己调用 JNI_CreateJavaVM()
,您应该能够使用 Delphi 的 RTL 内部使用的相同 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;
关于android - 从 Delphi 调用 JNI_OnLoad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48670592/