Invoke JNI_OnLoad from Delphi

Invoke JNI_OnLoad from Delphi

本文关键字:from Delphi OnLoad JNI Invoke      更新时间:2023-10-16

我想在我的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;
}

这是我加载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不会发生。

从这里所以请任何时候都可以从我的delphi代码调用。

谢谢

只是想知道为什么不调用JNI_OnLoad

JNI_OnLoad()通常由Java JVM调用,如果是加载本机库的一个(即Java代码调用System.loadLibrary()(。

由于在您的示例中不是这种情况,这就是为什么未调用JNI_OnLoad()的原因。您自己直接加载图书馆,因此您必须自己致电JNI_OnLoad()

Embarcadero在Embarcadero.Jni单元中声明TJNI_OnLoad功能指针类型。使用GetProcAddress()获取指向库导出的JNI_OnLoad()功能的指针,并将该指针分配给TJNI_OnLoad变量。然后,您可以像任何其他功能一样调用JNI_OnLoad()

后者我将JNIEnv* env作为全局变量保存在我的本机LIB

中的某些过程和功能中

JNI_OnLoad()JavaVM*指针作为输入。谁打电话给JNI_OnLoad()必须将指针传递给有效的JavaVM对象。

Java JVM通常会为您处理。但是,由于您自己加载了库,因此必须自己调用JNI_OnLoad(),因此必须从Delphi代码提供JavaVM对象。您应该能够使用Delphi的RTL内部使用的JavaVM对象,而不是您自己调用JNI_CreateJavaVM(),而是能够使用相同的CC_20对象-RTL的System单元中的JavaMachine指针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;