JNA - Radar ZHAW

Werbung
INE 2
Java Native Access
I'm
I'maanative
nativeAmerican
American
■ Einführung
■ Dynamische Bibliotheken
■ Java-Signatur
Hello JNA
■ Mittels Java Native Access (JNA) lassen sich native C Funktionen einfach von
Java aus aufrufen.
■ Es wird einfach ein Interface definiert, in dem für jede DLL Funktion eine
"passende" Java Methode definiert wird.
■ Diese kann dann mit INSTANCE.<FunktionsName> direkt aufgerufen werden.
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
/** Simple example of native library declaration and usage. */
public class HelloWorld {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary(
(Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
void printf(String format, Object ... args);
}
public static void main(String[] args) {
CLibrary.INSTANCE.printf("Hello, World\n");
for (int i = 0; i < args.length; i++) {
CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
}
}
}
School of Engineering
© K. Rege, ZHAW
2 von 17
Dynamische
Bibliotheken
School of Engineering
© K. Rege, ZHAW
3 von 17
Dynamische Bibliotheken
■ Dynamische Bibliotheken müssen speziell erzeugt werden
■
unter Windows mit der Endung DLL
■
Betriebssystem selber besteht aus einer Sammlung von DLLs
■ Sie stellen dem Linker (über Libs) die Funktionen zur Verfügung,
■ Es wird nicht die Funktion sondern lediglich ein Vermerk (Referenz) gespeichert
■ Der Lader löst die Referenz dynamisch auf und lädt die benötigten DLLs nach
■
Suchpfad für die DLLs
ist aktuelles Verzeichnis und
zusätzlich alle in der "PATH"
Umgebungsvariablen vermerkte
School of Engineering
Dependency Walker zur
Dependency Walker zur
Anzeige der Abhängigkeiten
Anzeige der Abhängigkeiten
© K. Rege, ZHAW
4 von 17
Export mit __declspec(dllexport)
■ Exportierte Funktionen müssen speziell gekennzeichnet werden
#define DLL_EXPORT __declspec(dllexport)
■ Von andern Modulen importierte ensprechend
#define DLL_EXPORT __declspec(dllimport)
■ Die Aufrufkonvention muss __cdecl sein
■ Am einfachsten mit einem Define (z.B. _DLL), das man über das Projekt setzt
#ifdef _DLL
// If accessing the data from inside the DLL
#define DLL_EXPORT __declspec(dllexport)
#else
// If accessing the data from outside the DLL
#define DLL_EXPORT __declspec(dllimport)
#endif
__cdecl void DLL_EXPORT foo(void);
■ Die exportierten Funktionen sind im LIB File gespeichert
School of Engineering
© K. Rege, ZHAW
5 von 17
Übersetzung im Überblick
■ Compilierung der Bibliothek und Klient und Ausführen
#include
#include
Compiler
Compiler
Namen
Namender
derDLL
DLL
vermerkt
vermerkt
DynLib.h
DynLib.dll
Beim
BeimLaden
Ladenwird
wird
die
referenzierte
die referenzierte
DLL
DLL(mit(mit)geladen
)geladen
DynLib.c
DynLib.lib
Beim
Beim
Compilieren
Compilierenwird
wird
das
h
File
das h File
included
included
Beim
BeimLinken
Linken
wird
wirddas
dasliblibFile
File
gebunden
gebunden
Lader
Lader
Compiler
Compiler
TestClient.exe
TestClient.c
School of Engineering
© K. Rege, ZHAW
6 von 17
DynLib.h
#ifndef DYNLIB1_H
#define DYNLIB1_H
#ifdef _DLL
// If accessing the data from inside the DLL
#define DLL_EXPORT __declspec(dllexport)
#else
// If accessing the data from outside the DLL
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef
__cplusplus
extern "C" {
#endif
void __cdecl DLL_EXPORT foo(void);
#ifdef
}
#endif
__cplusplus
#endif
/* DYNLIB1_H */
School of Engineering
© K. Rege, ZHAW
7 von 17
DynLib.c und TestClient.exe
■ Implementation der Library
#include "DynLib1.h"
#include <stdio.h>
void __cdecl foo() {
printf("Hello World\n");
}
■ Und Aufruf von foo() in TestClient (separates EXE)
#include <stdio.h>
#include <stdlib.h>
#include "DynLib1.h"
int main(int argc, char** argv) {
foo();
return (EXIT_SUCCESS);
}
School of Engineering
© K. Rege, ZHAW
8 von 17
Weiterer Vorteil von dynamischen Bibliotheken
■ C-Bibliotheken lassen sich von praktisch jeder Programmiersprache aus
aufrufen
■ Z.B. können GUIs mit Java (oder C#) entwickelt werden
■
■
■
einfacher
plattformunabhängig
sehr gute Werkzeuge vorhanden (sog. GUI Builder)
■ Der Aufruf der C Bibliotheksfunktion in Java dann via JNA (später)
School of Engineering
© K. Rege, ZHAW
9 von 17
LoadLibrary
School of Engineering
© K. Rege, ZHAW
10 von 17
LoadLibrary
■ Mittels Native.loadLibrary wird die DLL geladen
■
■
sie muss im Pfad (definiert durch die PATH Umgebungsvariablen)
oder im Ausführungsverzeichnis liegen
■ Mittels Platform.isWindows() kann abgefragt werden, ob man sich auf einer
Windows Platform befindet
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary(
(Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
void printf(String format, Object... args);
}
School of Engineering
© K. Rege, ZHAW
11 von 17
Definition der Signatur
■ Anhand des Header Files kann die Signatur der Java Methode "abgeleitet"
werden.
■ void printf(const char *format, ...) -> void printf(String format, Object... args)
■ Die Abbildungsregeln der Datantypen:
School of Engineering
© K. Rege, ZHAW
12 von 17
… Definition der Signatur
■ Strings werden automatisch umgewandet
■ Structs als Parameter sind etwas komplizierter -> siehe Praktikum
■ Vorsicht: Fehler in der Abbildung werden nicht erkannt und führen zu
Laufzeitfehler.
School of Engineering
© K. Rege, ZHAW
13 von 17
Aufruf der C Funktion
■ Der Aufruf selber wird über INSTANCE ganz "normal"
{
...
public static void main(String[] args) {
CLibrary.INSTANCE.printf("Hello, World\n");
}
}
School of Engineering
© K. Rege, ZHAW
14 von 17
Noch Fragen
School of Engineering
© K. Rege, ZHAW
15 von 17
Bsp: Kernel Funktionen
■ Aufruf von Kernel Funktionen
import com.sun.jna.Library;
import com.sun.jna.Native;
/** Simple example of Windows native library declaration and usage. */
public class BeepExample {
public interface Kernel32 extends Library {
// FREQUENCY is expressed in hertz and ranges from 37 to 32767
// DURATION is expressed in milliseconds
Kernel32 INSTANCE = (Kernel32 ) Native.loadLibrary(
"kernel32", Kernel32.class);
public boolean Beep(int FREQUENCY, int DURATION);
public void Sleep(int DURATION);
}
public static void main(String[] args) {
Kernel32.INSTANCE.Beep(300, 500);
Kernel32.INSTANCE.Sleep(500);
Kernel32.INSTANCE.Beep(698, 500);
}
}
School of Engineering
© K. Rege, ZHAW
16 von 17
Bsp: User32 Funktionen
■ Aufruf von User32 Funktionen: Lock Computer
import com.sun.jna.*;
public class JNASample {
public interface User32 extends Library {
User32 INSTANCE = (User32) Native.loadLibrary("User32", User32.class);
public boolean LockWorkStation();
}
public static void main(String args[]) {
User32.INSTANCE.LockWorkStation();
}
}
School of Engineering
© K. Rege, ZHAW
17 von 17
Herunterladen