Maison > Java > javaDidacticiel > le corps du texte

Utilisation de Java Native Access (JNA) pour appeler l'API MacOS

Susan Sarandon
Libérer: 2024-09-23 16:16:59
original
674 Les gens l'ont consulté

Using Java Native Access (JNA) to call MacOS API

Introduction

Voici un exemple simple sur la façon d'utiliser JNA avec l'API MacOS. Je ne vais pas expliquer cela, car j'apprends encore, mais je garde le code au minimum pour le rendre plus facile à comprendre et avoir une idée de base sur la façon de le faire à d'autres fins.

La plupart du code provient d'Intellij-Community (licence Apache).

Dépendance

Tout ce dont nous avons besoin, c'est de la plateforme JNA.

<dependency>
  <groupId>net.java.dev.jna</groupId>
  <artifactId>jna-platform</artifactId>
  <version>5.13.0</version>
</dependency>
Copier après la connexion

Code

Il y a au total 4 fichiers de code source. L'ID est copié depuis IntelliJ sans modification. MyFoundation et MyFoundationLibrary sont respectivement supprimés de Foundation et FoundationLibrary.

Application.java

package org.example;

import com.sun.jna.Pointer;

import static org.example.MyFoundation.*;

public class Application {

    public static void main(String[] args) throws Exception {
        ID processInfoCls = getObjcClass("NSProcessInfo");
        Pointer processInfoSel = createSelector("processInfo");
        Pointer processNameSel = createSelector("processName");

        ID processInfo = invoke(processInfoCls, processInfoSel);
        ID processNameNSString = invoke(processInfo, processNameSel);
        String processName = toStringViaUTF8(processNameNSString);
        System.out.println(processName);
    }

}
Copier après la connexion

ID.java

package org.example;

import com.sun.jna.NativeLong;

public final class ID extends NativeLong {

    public ID() {
    }

    public ID(long peer) {
        super(peer);
    }

    public static final ID NIL = new ID(0L);

    public boolean booleanValue() {
        return intValue() != 0;
    }
}
Copier après la connexion

MaFoundationLibrary.java

public interface MyFoundationLibrary extends Library {

    int kCFStringEncodingUTF8 = 0x08000100;

    ID objc_getClass(String className);

    Pointer sel_registerName(String selectorName);

    int CFStringGetLength(ID theString);

    byte CFStringGetCString(ID theString, byte[] buffer, int bufferSize, int encoding);

}
Copier après la connexion

MaFondation.java

package org.example;

import com.sun.jna.*;

import java.lang.reflect.Proxy;
import java.util.Collections;

public class MyFoundation {
    private static final MyFoundationLibrary myFoundationLibrary;
    private static final Function myObjcMsgSend;

    static {
        myFoundationLibrary = Native.load("Foundation", MyFoundationLibrary.class, Collections.singletonMap("jna.encoding", "UTF8"));
        NativeLibrary nativeLibrary = ((Library.Handler) Proxy.getInvocationHandler(myFoundationLibrary)).getNativeLibrary();
        myObjcMsgSend = nativeLibrary.getFunction("objc_msgSend");
    }

    public static ID getObjcClass(String className) {
        return myFoundationLibrary.objc_getClass(className);
    }

    public static Pointer createSelector(String s) {
        return myFoundationLibrary.sel_registerName(s);
    }

    private static Object [] prepInvoke(ID id, Pointer selector, Object[] args) {
        Object[] invokArgs = new Object[args.length + 2];
        invokArgs[0] = id;
        invokArgs[1] = selector;
        System.arraycopy(args, 0, invokArgs, 2, args.length);
        return invokArgs;
    }

    public static ID invoke(final ID id, final Pointer selector, Object... args) {
        // objc_msgSend is called with the calling convention of the target method
        // on x86_64 this does not make a difference, but arm64 uses a different calling convention for varargs
        // it is therefore important to not call objc_msgSend as a vararg function
        return new ID(myObjcMsgSend.invokeLong(prepInvoke(id, selector, args)));
    }

    public static String toStringViaUTF8(ID cfString) {
        if (ID.NIL.equals(cfString)) return null;

        int lengthInChars = myFoundationLibrary.CFStringGetLength(cfString);
        int potentialLengthInBytes = 3 * lengthInChars + 1; // UTF8 fully escaped 16 bit chars, plus nul

        byte[] buffer = new byte[potentialLengthInBytes];
        byte ok = myFoundationLibrary.CFStringGetCString(cfString, buffer, buffer.length, MyFoundationLibrary.kCFStringEncodingUTF8);
        if (ok == 0) throw new RuntimeException("Could not convert string");
        return Native.toString(buffer);
    }

}
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal