j'ai trouvé une bonne mise en œuvre de JNI: https://sites.google.com/site/aminer68/jni-wrapper-for-delphi-and-freepascalEn utilisant JNI dans CCPF/Lazarus sur Linux
Il a la version 2.85, et le texte suivant a été écrit en Mars 2016, mais il est écrit pour Windows.
Mais j'eu aucun problème à sauter/enlever tous les trucs associés à Windows (ce que Lazare n'a pas enlevé), mais mon travail échoue encore
Je l'ai fait comme ceci:
procedure TJavaRuntime.Initialize;
begin
if libHandle <> 0 then
exit; // already initialized.
FRuntimeLib := '/usr/lib/jvm/java-8-oracle/jre/lib/amd64/server/libjvm.so';
libHandle := LoadLibrary(PChar(FRuntimeLib));
if libHandle = 0 then
raise EJavaRuntimeCreation.Create('Could not load library ' + FRuntimeLib);
@CreateVM := getProcAddress(libHandle, 'JNI_CreateJavaVM');
@GetDefaultArgs := getProcAddress(libHandle, 'JNI_GetDefaultJavaVMInitArgs');
@GetCreatedVMs := getProcAddress(libHandle, 'JNI_GetCreatedJavaVMs');
if (@CreateVM = Nil) or (@GetDefaultArgs = Nil) or (@GetCreatedVMs = Nil) then
raise EJavaRuntimeCreation.Create('Library ' + FRuntimeLib + ' is not valid.');
vmargs2.version := $00010008;
GetDefaultArgs(@vmargs2);
end;
Vous voyez, Je charge la bibliothèque jvm comme nécessaire sous Linux. libHandle devient non nul, donc je pense qu'il le charge bien (si je crée une faute d'orthographe dans le nom de bibliothèque, libHandle reste zéro.)
La découverte des procadresses semble échouer. @CreateVM:>
des renseignements généraux sur CreateVM:
CreateVM : TCreateVM;
TCreateVM = function (vm : PPJavaVM ; penv : PPJNIEnv ; p : Pointer) : jint; {$IFDEF WIN32} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
(en passant, cdecl est actif, stdcall est grisé dans l'éditeur Lazarus)
J'essaie d'appeler un, comme cette fonction en TJavaRuntime.GetVM
Comme ici
if CreateVM(@pvm, @penv, args) <>0 then
raise EJavaRuntimeCreation.Create('Could not create JVM');
Il ne va pas à l'exception, mais déclenche une autre exception: Le projet jtest1 a levé la classe d'exception 'Externe: SIGSEGV'. À l'adresse 7FFFE62582B4
J'ai lu quelque part que SIGSEGV entre dans un emplacement de mémoire qui est un défaut d'accès à la mémoire illégale. Cela me ramène au code où l'adresse de CreateVM est récupéré de cette façon:
@CreateVM := getProcAddress(DLLHandle, 'JNI_CreateJavaVM');
Je suis sûr qu'une fonction de ce nom existe dans cette bibliothèque:
~ > nm -D /usr/lib/jvm/java-8-oracle/jre/lib/amd64/server/libjvm.so
---fragment
000000000070e0f0 T jio_snprintf
000000000070de80 T jio_vfprintf
000000000070e0d0 T jio_vsnprintf
00000000006d0880 T JNI_CreateJavaVM
00000000006cd1d0 T JNI_GetCreatedJavaVMs
00000000006cd210 T JNI_GetDefaultJavaVMInitArgs
000000000070ee00 T JVM_Accept
0000000000713990 T JVM_ActiveProcessorCount
0000000000715a20 T JVM_AllocateNewArray
0000000000727340 T JVM_AllocateNewObj
Ainsi l'appel avec getProcAddress (.....) ne conduit pas à une adresse valide. Il se peut que la fonction LoadLibrary (PChar (FRuntimeLib)) ne charge pas correctement la bibliothèque, bien qu'elle dispose d'un handle valide. (j'ai aussi essayé SafeLoadLibrary (FRuntimeLib). Ou le GetProcAddress (.....) a quelques problèmes (Soit dit en passant, j'ai essayé aussi GetProcedureAddress)
J'ai aussi essayé d'autres jvm-bibliothèques, de sorte que. .? ne peut pas être le problème
Qui sait ce qui se passe mal ici
Merci à l'avance
Merci, Marco, J'ai trouvé des informations sur cmem: http://wiki.lazarus.freepascal.org/CMem maintenant est d'abord dans mon fichier lpr. Ne résout pas le problème. En effet beaucoup de stdcall. Maintenant {$ IFDEF WIN32} stdcall; {$ ENDIF} {$ IFDEF LINUX} cdecl; {$ ENDIF}, et les cdecl sont actifs. Les fonctions que j'appelle avec @, comme CreateVM sont nécessaires pour initialiser. Sans eux rien ne fonctionne (comme je le comprends bien). Je ne sais pas si je les utilise correctement, je les utilise de la manière originale du code. Je ne comprends pas votre dernière remarque, pour votre information, mon code et la bibliothèque sont sur le même ordinateur. –
Si le code source de l'en-tête et le code que vous utilisez pour appeler l'en-tête ne proviennent pas de la même source (mais pour un en-tête ou une tête différente), vous risquez de traduire un paramètre pointeur avec VAR. aiguille. –
Salut Marco, il n'y a pas d'en-têtes utilisés dans Pascal loadLibrary et getProcAddress, tout ce que nous faisons est d'utiliser les noms qui sont publiés par la bibliothèque. La bibliothèque elle-même doit avoir été chargée, le handle est devenu non nul. Je l'ai vérifié en déformant délibérément le chemin, puis la poignée devient nulle. Donc, quand la bibliothèque est bien chargée, qu'est-ce que je pense, alors le problème doit être dans l'appel getProcAddress. J'ai aussi essayé de charger un autre libjvm.so, qui avait le même résultat. Je pense que c'est un problème de FPC/Lazarus, mais je n'en suis pas sûr. Je l'ai également posté sur leurs listes de diffusion. –