Java Native Access - Wikipedia Overview - JNA API Documentation
Ich habe hier über Python-Typen geschrieben. Python: ctypes-Mustersammlung
Es ist mühsam, über neues Material nachzudenken, daher </ s> ist der Inhalt der Probe genau der gleiche.
Bringen Sie jedes .jar von den folgenden Seiten. https://mvnrepository.com/artifact/net.java.dev.jna/jna https://mvnrepository.com/artifact/net.java.dev.jna/jna-platform
Wählen Sie die Version aus und laden Sie "jar" in die Spalte "Dateien" herunter. Fügen Sie das heruntergeladene Glas zum Klassenpfad hinzu.
Wenn Sie Gradle verwenden, fügen Sie den Abhängigkeiten von build.gradle zwei Zeilen hinzu, anstatt das Glas selbst herunterzuladen.
dependencies {
// ...
//Die folgenden zwei Zeilen wurden hinzugefügt
implementation 'net.java.dev.jna:jna:4.5.2'
implementation 'net.java.dev.jna:jna-platform:4.5.2'
// ...
}
Unter Verwendung der Windows-API (Win32API) als Thema werden Muster in verschiedenen Fällen zusammengefasst.
Es ist ein einfaches Programm, das nur 1 Sekunde lang schläft. Zuerst von hier.
JNISample.java
import com.sun.jna.Library;
import com.sun.jna.Native;
public class JNISample {
public interface Kernel32 extends Library {
Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
void Sleep(int dwMilliseconds);
}
public static void main(String[] args) {
System.out.println("started");
Kernel32.INSTANCE.Sleep(1000);
System.out.println("finished");
}
}
Lassen Sie uns das Meldungsfeld mit der MessageBox-Funktion anzeigen.
JNISample.java
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
public class JNISample {
public interface User32 extends Library {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
// A/Fügen Sie A hinzu, wenn zwischen W unterschieden wird
int MessageBoxA(Pointer hWnd, String lpText, String lpCaption, int uType);
}
public static void main(String[] args) {
User32.INSTANCE.MessageBoxA(null, "Prüfung", "Titel", 0);
}
}
Wie wir später sehen werden, hat das Fensterhandle in einem 64-Bit-Betriebssystem einen 64-Bit-Wert, daher wird es als Argument vom Typ "Zeiger" verwendet.
Wenn der Quellcode in MS932 (Shift-JIS, CP932) geschrieben ist, funktioniert dies, aber wenn der Quellcode in UTF-8 geschrieben ist, werden die Zeichen verstümmelt. Verwenden Sie daher die Unicode-Version der API und setzen Sie das Zeichenfolgenargument auf den Typ "WString".
JNISample.java
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
public class JNISample {
public interface User32 extends Library {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
// A/Addiere W, wenn es einen Unterschied zwischen W gibt
int MessageBoxW(Pointer hWnd, WString lpText, WString lpCaption, int uType);
}
public static void main(String[] args) {
User32.INSTANCE.MessageBoxW(null, new WString("Prüfung"), new WString("Titel"), 0);
}
}
Das ist in Ordnung.
Stellen Sie -encoding
von javac
entsprechend ein. (Wenn Sie Eclipse verwenden, müssen Sie sich nicht zu viele Sorgen machen.)
Nicht auf die Windows-API beschränkt. Wenn es eine Funktion gibt, die den Typ "wchar_t *" usw. empfängt, übergeben wir sie mit "WString".
Von nun an werden wir die Übergabe von Zeichenfolgen basierend auf Unicode behandeln.
GetComputerName-Funktion --MSD
Es ist der Fluss von. Sind die folgenden Punkte die Punkte?
getValue ()
erhalten LongByReference
etc.Native.toString ()
in String
new String ()
konvertiert werden kann, aber es wird nicht als Null-Ende interpretiert und es folgt Staub.JNISample.java
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;
public class JNISample {
public interface Kernel32 extends Library {
Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
boolean GetComputerNameW(char[] lpBuffer, IntByReference lpnSize);
}
public static void main(String[] args) {
IntByReference lenComputerName = new IntByReference();
Kernel32.INSTANCE.GetComputerNameW(null, lenComputerName);
char[] computerName = new char[lenComputerName.getValue()];
Kernel32.INSTANCE.GetComputerNameW(computerName, lenComputerName);
System.out.println(Native.toString(computerName));
}
}
Ausführungsergebnis: Computername
taro-pc
Da Arrays als Referenz übergeben werden, ist es möglich, Arrays anstelle von "IntByReference" zu verwenden.
import com.sun.jna.Library;
import com.sun.jna.Native;
public class JNISample {
public interface Kernel32 extends Library {
Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
//Der Typ von lpnSize ist int[]Zu
boolean GetComputerNameW(char[] lpBuffer, int[] lpnSize);
}
public static void main(String[] args) {
//Verwenden Sie ein Array der Länge 1
int[] lenComputerName = new int[1];
Kernel32.INSTANCE.GetComputerNameW(null, lenComputerName);
char[] computerName = new char[lenComputerName[0]];
Kernel32.INSTANCE.GetComputerNameW(computerName, lenComputerName);
System.out.println(Native.toString(computerName));
}
}
Definieren Sie die Struktur in einer Klasse, die von com.sun.jna.Structure
erbt.
--Listet Mitgliedsvariablen als öffentlich auf
getFieldOrder ()
, um die Reihenfolge im Speicher zu definieren
--Mitgliedvariablen müssen nur proportional aufgelistet werden
--This.getClass (). GetFields ()
kann nicht verwendet werden, da die Reihenfolge undefiniert ist [^ 1]Wenn Sie die Struktur (Klasse) als Argument angeben, wird sie automatisch als Referenz übergeben.
JNISample.java
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Structure;
public class JNISample {
public interface User32 extends Library {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
boolean GetCursorPos(POINT lpPoint);
}
public static class POINT extends Structure {
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("X", "Y");
}
public int X;
public int Y;
}
public static void main(String[] args) {
POINT pt = new POINT();
User32.INSTANCE.GetCursorPos(pt);
System.out.println(String.format("x = %d, y = %d", pt.X, pt.Y));
}
}
Ausführungsergebnis: Mauszeigerposition
x = 340, y = 1061
Als nächstes folgt die Geschichte, wenn ein char-Array fester Länge oder eine andere Struktur in die Struktur kommt.
FindFirstFile-Funktion --MSD FindNextFile-Funktion --MSD FindCLose-Funktion --MSD
UINT_PTR
usw.) WPARAM
/ LPARAM
Pointer.nativeValue (ptr)
abrufenJNISample.java
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.WString;
public class JNISample {
public interface Kernel32 extends Library {
Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
Pointer FindFirstFileW(WString lpFileName, WIN32_FIND_DATAW lpFindFileData);
boolean FindNextFileW(Pointer hFindFile, WIN32_FIND_DATAW lpFindFileData);
boolean FindClose(Pointer hFindFile);
}
public static final int MAX_PATH = 260;
public static final Pointer INVALID_HANDLE_VALUE = new Pointer(-1);
public static class FILETIME extends Structure {
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("dwLowDateTime", "dwHighDateTime");
}
public int dwLowDateTime;
public int dwHighDateTime;
}
public static class WIN32_FIND_DATAW extends Structure {
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(
"dwFileAttributes", "ftCreationTime", "ftLastAccessTime", "ftLastWriteTime",
"nFileSizeHigh", "nFileSizeLow", "dwReserved0", "dwReserved1",
"cFileName", "cAlternateFileName", "dwFileType", "dwCreatorType", "wFinderFlags"
);
}
public int dwFileAttributes;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public int nFileSizeHigh;
public int nFileSizeLow;
public int dwReserved0;
public int dwReserved1;
public char[] cFileName = new char[MAX_PATH];
public char[] cAlternateFileName = new char[14];
public int dwFileType;
public int dwCreatorType;
public short wFinderFlags;
}
public static void main(String[] args) {
String pattern = "C:\\Windows\\*.exe";
WIN32_FIND_DATAW findData = new WIN32_FIND_DATAW();
Pointer hfind = Kernel32.INSTANCE.FindFirstFileW(new WString(pattern), findData);
if (hfind != INVALID_HANDLE_VALUE) {
do {
System.out.println(Native.toString(findData.cFileName));
} while (Kernel32.INSTANCE.FindNextFileW(hfind, findData));
}
Kernel32.INSTANCE.FindClose(hfind);
}
}
Ausführungsergebnis: Direkt unter dem Windows-Ordner.exe Dateiliste
bfsvc.exe
explorer.exe
HelpPane.exe
hh.exe
notepad.exe
regedit.exe
RtCRU64.exe
splwow64.exe
winhlp32.exe
write.exe
GetOpenFileName-Funktion --MSD
--Funktionen, die sizeof
in der Structure.size ()
Methode entsprechen
char []
angeben (es wird wie oben beschrieben als Wertübergabe behandelt)ByteBuffer.allocateDirect ()
reservierenJNISample.java
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.WString;
public class JNISample {
public interface Comdlg32 extends Library {
Comdlg32 INSTANCE = (Comdlg32) Native.loadLibrary("comdlg32", Comdlg32.class);
boolean GetOpenFileNameW(OPENFILENAME lpofn);
}
public static class OPENFILENAME extends Structure {
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(
"lStructSize", "hwndOwner", "hInstance", "lpstrFilter", "lpstrCustomFilter", "nMaxCustFilter",
"nFilterIndex", "lpstrFile", "nMaxFile", "lpstrFileTitle", "nMaxFileTitle", "lpstrInitialDir",
"lpstrTitle", "Flags", "nFileOffset", "nFileExtension", "lpstrDefExt", "lCustData", "lpfnHook",
"lpTemplateName", "pvReserved", "dwReserved", "FlagsEx"
);
}
public int lStructSize;
public Pointer hwndOwner;
public Pointer hInstance;
public WString lpstrFilter;
public WString lpstrCustomFilter;
public int nMaxCustFilter;
public int nFilterIndex;
public ByteBuffer lpstrFile;
public int nMaxFile;
public WString lpstrFileTitle;
public int nMaxFileTitle;
public WString lpstrInitialDir;
public WString lpstrTitle;
public int Flags;
public short nFileOffset;
public short nFileExtension;
public WString lpstrDefExt;
public Pointer lCustData;
public Pointer lpfnHook;
public WString lpTemplateName;
public Pointer pvReserved;
public int dwReserved;
public int FlagsEx;
}
public static void main(String[] args) {
OPENFILENAME ofn = new OPENFILENAME();
final int lenFilenameBufferInChars = 1024;
ByteBuffer buf = ByteBuffer.allocateDirect(lenFilenameBufferInChars * 2);
ofn.lStructSize = ofn.size();
ofn.lpstrFilter = new WString("Textdatei\0*.txt\0\0");
ofn.lpstrFile = buf;
ofn.nMaxFile = lenFilenameBufferInChars;
ofn.lpstrTitle = new WString("Bitte wählen Sie die Datei");
ofn.Flags = 0x00001000; // OFN_FILEMUSTEXIST
boolean ret = Comdlg32.INSTANCE.GetOpenFileNameW(ofn);
if (ret) {
CharBuffer cbuf = buf.order(ByteOrder.LITTLE_ENDIAN).asCharBuffer();
char[] arr = new char[cbuf.capacity()];
cbuf.get(arr);
System.out.println(Native.toString(arr));
} else {
System.out.println("wurde storniert");
}
}
}
Ausführungsergebnis: Ausgewählter Dateiname
C:\Users\taro\test.txt
An diesem Punkt wird es ziemlich schwierig. Ich hatte ziemlich viel Probleme damit, was ich mit den Typen der Mitglieder der Struktur anfangen sollte.
Einige Windows-API-Funktionen rufen die angegebene Rückruffunktion auf, wenn ein Ereignis auftritt. Beispielsweise benachrichtigt die Funktion "EnumWindows", die vorhandene Fenster auflistet, das gefundene Fenster durch eine Rückruffunktion.
Der Fluss ist wie folgt.
Rückruf
-Schnittstelle erben invoke
invoke
der zuvor definierten Schnittstelle wurde implementiertDa es schwer zu verstehen ist, selbst wenn nur die Fenstergriffe aufgelistet sind, wird ein Beispiel für die Ausgabe mit dem Fenstertitel gezeigt.
JNISample.java
import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
public class JNISample {
public interface User32 extends Library {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
boolean EnumWindows(EnumWindowsProc lpEnumFunc, Pointer lParam);
int GetWindowTextW(Pointer hWnd, char[] lpString, int nMaxCount);
}
public interface EnumWindowsProc extends Callback {
public boolean invoke(Pointer hWnd, Pointer lParam);
}
public static void main(String[] args) {
User32.INSTANCE.EnumWindows(new EnumWindowsProc() {
@Override
public boolean invoke(Pointer hWnd, Pointer lParam) {
char[] windowText = new char[1024];
User32.INSTANCE.GetWindowTextW(hWnd, windowText, windowText.length);
System.out.println(String.format("%x: %s", Pointer.nativeValue(hWnd), Native.toString(windowText)));
return true;
}
}, null);
}
}
Ausführungsergebnis: Liste der geöffneten Fenster (Auszug)
20730:Schneller Zugang
10226:Batterieanzeige
9d09aa: eclipse
f05b4:Taschenrechner
Ich frage mich, was ich probieren soll, weil ich es in der Windows-API nicht oft verwende, aber hier verwende ich die Funktion wvsprintf
, die eine Funktion für das Zeichenfolgenformat ist.
In Java können Sie dasselbe mit der Funktion String.format ()
tun, sodass es nicht erforderlich ist, sie von Java aus auszuführen.
Diese Funktion hat eine spezielle Methode zum Übergeben von Argumenten, entspricht jedoch dem Übergeben eines Zeigers auf eine Zeichenfolge (dh eines Zeigers auf einen Zeiger in der Sprache C), solange Sie nur eine Zeichenfolge übergeben. (Ich werde hier nicht über zwei oder mehr sprechen)
Erstellen Sie zunächst ein Array von Zeichenfolgen und übergeben Sie das Array als Referenz.
JNISample.java
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.WString;
public class JNISample {
public interface User32 extends Library {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
int wvsprintfW(char[] lpOutput, WString lpFormat, WString[] arglist);
}
public static void main(String[] args) {
char[] buf = new char[1024];
String name = "Michael";
WString[] argArray = new WString[] {new WString(name)};
User32.INSTANCE.wvsprintfW(buf, new WString("My name is %s"), argArray);
System.out.println(Native.toString(buf));
}
}
Ausführungsergebnis: Formatierte Zeichenfolge
My name is Michael
Mach dasselbe anders. Es sieht ein wenig umständlich aus, ist aber eine zeigerbewusste Methode.
JNISample.java
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.WTypes;
import com.sun.jna.ptr.PointerByReference;
public class JNISample {
public interface User32 extends Library {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
int wvsprintfW(char[] lpOutput, WString lpFormat, Pointer arglist);
}
public static void main(String[] args) {
char[] buf = new char[1024];
String name = "Michael";
WTypes.LPWSTR pname = new WTypes.LPWSTR(name); // wchar_t *
PointerByReference argArray = new PointerByReference(pname.getPointer()); // wchar_t **
User32.INSTANCE.wvsprintfW(buf, new WString("My name is %s"), argArray.getPointer());
System.out.println(Native.toString(buf));
}
}
Der in der Windows-API angezeigte Typ "LPWSTR" wurde angezeigt, ist jedoch eine Unterklasse von "PointerType". Da "IntByReference" usw. auch "PointerType" erben, kann es auf die gleiche Weise behandelt werden wie diese "ByReference" -Serien.
Das Argument von "arglist" ist vom Typ "Pointer", kann aber auch vom Typ "PointerByReference" sein. In diesem Fall können Sie "argArray" unverändert ohne Konvertierung übergeben (ohne "getPointer ()"). Auf diese Weise können Sie auch bei gleicher Verarbeitung auf verschiedene Arten schreiben, aber ich denke, Sie sollten die Methode wählen, die für jedes Mal geeignet ist.
Vielleicht können wir mehr tun, aber ich denke, es reicht aus, ein solches Muster als Ausgangspunkt zu haben. Sie können sich andere Muster ansehen, wenn Sie es tun möchten (wenn Sie es tun müssen).
Recommended Posts