」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 使用Java Native Access (JNA)呼叫MacOS API

使用Java Native Access (JNA)呼叫MacOS API

發佈於2024-09-27
瀏覽:830

Using Java Native Access (JNA) to call MacOS API

介紹

這是一個關於如何將 JNA 與 MacOS API 結合使用的簡單範例。我不會解釋這一點,因為我仍在學習,但我將程式碼保持最少,以便更容易理解並了解如何將其用於其他目的的基本概念。

大部分程式碼來自 Intellij-Community(Apache 授權)。

依賴性

我們需要的是 jna-platform。

net.java.dev.jnajna-platform5.13.0

程式碼

原始碼檔案共有4個。 ID 是從 IntelliJ 複製而來,未經修改。 MyFoundation 和 MyFoundationLibrary 分別從 Foundation 和 FoundationLibrary 中刪除。

應用程式.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);
    }

}

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;
    }
}

MyFoundationLibrary.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);

}

MyFoundation.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);
    }

}
版本聲明 本文轉載於:https://dev.to/franzwong/using-java-native-access-jna-to-call-macos-api-2pi0?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 對於專業開發人員來說最有用的 VS Code 快捷方式?
    對於專業開發人員來說最有用的 VS Code 快捷方式?
    VS Code 中 20 個最有用的快捷鍵 一般導航 指令面板:存取 VS Code 中的所有可用指令。 Ctrl Shift P (Windows/Linux) 或 Cmd Shift P (macOS) 快速開啟:按名稱快速開啟檔案。 Ctrl P (Windows/Linux) 或 Cmd ...
    程式設計 發佈於2024-11-06
  • 何時使用“composer update”與“composer install”?
    何時使用“composer update”與“composer install”?
    探索composer update和composer install之間的區別Composer是一個流行的PHP依賴管理器,提供兩個關鍵命令:composer update和composer install。雖然它們具有管理依賴關係的共同目標,但它們具有不同的目的並以不同的方式運作。 Compose...
    程式設計 發佈於2024-11-06
  • Python 中的物件導向程式設計 (OOP):類別和物件解釋
    Python 中的物件導向程式設計 (OOP):類別和物件解釋
    面向对象编程 (OOP) 是软件开发中使用的关键方法。 在本文中,我们将探讨 OOP 的主要思想,特别是 Python 中的类、对象、继承和多态性。 在本指南结束时,您将了解如何使用 OOP 原则组织 Python 代码,使您的程序更加模块化、可重用且更易于维护。 什么是面向对象编...
    程式設計 發佈於2024-11-06
  • 在 Git 中切換分支而不丟失您的工作
    在 Git 中切換分支而不丟失您的工作
    作为开发人员,我们经常发现自己处于这样的情况:当我们深入编写功能时,突然有一个紧急问题需要我们立即关注。为了解决这个问题,我们需要切换 Git 中的分支。但是,如果我们尚未提交当前的更改,那么这样做可能会有风险。我们可能会失去工作或面临合并冲突。 在这篇文章中,我将引导您了解两种在 Git 中切换分...
    程式設計 發佈於2024-11-06
  • shell 中的 Props 與回呼
    shell 中的 Props 與回呼
    在這篇文章中,我將帶您了解一個實際場景,其中父元件(ListBox) 與子元件(AlertComponent ) 使用props 和回呼。 當您希望子元件與父元件通訊以維護狀態或觸發操作時,這在 React 中非常有用。 讓我們透過這個例子來理解: 我有一個 ListBox 元件,用於顯示項目清...
    程式設計 發佈於2024-11-06
  • 如何使用 Python 的 argparse 模組將值列表作為命令列參數傳遞?
    如何使用 Python 的 argparse 模組將值列表作為命令列參數傳遞?
    如何使用 argparse 將清單作為命令列參數傳遞? 在 Python 的 argparse 模組中,您可以傳遞清單使用 nargs 或附加選項作為命令列參數。 nargs使用 nargs 指定期望的參數數量。例如,nargs=' 表示一個或多個參數,nargs='*' 表...
    程式設計 發佈於2024-11-06
  • 如何解決 ES6 模組中的「意外令牌匯出」錯誤?
    如何解決 ES6 模組中的「意外令牌匯出」錯誤?
    意外的令牌導出:擁抱ES6 模組支援嘗試執行ES6 程式碼時遇到「意外的代幣匯出」錯誤可能會令人困惑問題。當執行時間環境缺乏對您正在使用的 EcmaScript 模組 (ESM) 語法的支援時,就會發生此錯誤。 了解 ESM:ESM,通常稱為「ES6 Modules」引入了 JavaScript 的...
    程式設計 發佈於2024-11-06
  • Next.js 簡介:建立您的第一個應用程式
    Next.js 簡介:建立您的第一個應用程式
    Next.js 是一种流行的 React 框架,使开发人员能够创建快速的服务器渲染应用程序。它提供了强大的开箱即用功能,例如静态站点生成 (SSG)、服务器端渲染 (SSR) 和 API 路由。在本指南中,我们将逐步介绍构建您的第一个 Next.js 应用程序的过程,重点关注关键概念和实际示例。 ...
    程式設計 發佈於2024-11-06
  • 使用 ChatGPT 建立訂單處理服務(貢獻努力)並已完成
    使用 ChatGPT 建立訂單處理服務(貢獻努力)並已完成
    人工智能为改变和提高我的日常工作效率做出了贡献 作为一名开发人员,当您的时间有限时,构建订单处理服务有时会让人感到不知所措。然而,借助 ChatGPT 等人工智能驱动的开发工具的强大功能,您可以通过生成代码、设计实体和逐步解决问题来显着加快流程。在本文中,我将向您介绍如何使用 ChatGPT 在短短...
    程式設計 發佈於2024-11-06
  • 如何在 Django 中記錄所有 SQL 查詢?
    如何在 Django 中記錄所有 SQL 查詢?
    如何在 Django 中記錄 SQL 查詢記錄 Django 應用程式執行的所有 SQL 查詢有利於偵錯和效能分析。本文提供了有關如何有效實現此目標的逐步指南。 配置要記錄所有SQL 查詢,包括管理網站產生的查詢,請將以下程式碼片段整合到settings.py 檔案中的LOGGING 欄位:LOGG...
    程式設計 發佈於2024-11-06
  • JavaScript 是同步還是異步,是單執行緒還是多執行緒? JavaScript程式碼是如何執行的?
    JavaScript 是同步還是異步,是單執行緒還是多執行緒? JavaScript程式碼是如何執行的?
    JavaScript 是一種同步、單執行緒語言,一次只能執行一個指令。僅噹噹前行執行完畢後,才會移至下一行。但是,JavaScript 可以使用事件循環、Promises、Async/Await 和回呼佇列執行非同步操作(JavaScript 預設是同步的)。 JavaScript程式碼是如何執行...
    程式設計 發佈於2024-11-06
  • 如何從 PHP 中的物件數組中提取一列屬性?
    如何從 PHP 中的物件數組中提取一列屬性?
    PHP:從物件數組中高效提取一列屬性許多程式設計場景都涉及使用物件數組,其中每個物件可能有多個屬性。有時,需要從每個物件中提取特定屬性以形成單獨的陣列。在 PHP 中,在不借助循環或外部函數的情況下用一行程式碼實現此目標可能很棘手。 一個可能的方法是利用 array_walk() 函數和 creat...
    程式設計 發佈於2024-11-06
  • 建構 PHP Web 專案的最佳實踐
    建構 PHP Web 專案的最佳實踐
    規劃新的 PHP Web 專案時,考慮技術和策略方面以確保成功非常重要。以下是一些規則來引導您完成整個過程: 1. 定義明確的目標和要求 為什麼重要:清楚了解專案目標有助於避免範圍蔓延並與利害關係人設定期望。 行動: 建立具有特定功能的專案大綱。 確定核心特徵和潛在的發展階段。 ...
    程式設計 發佈於2024-11-06
  • 如何在不使用巢狀查詢的情況下從 MySQL 中的查詢結果指派使用者變數?
    如何在不使用巢狀查詢的情況下從 MySQL 中的查詢結果指派使用者變數?
    MySQL 中根據查詢結果分配使用者變數背景和目標根據查詢結果分配使用者定義的變數可以增強資料庫操作能力。本文探討了在 MySQL 中實現此目的的方法,而無需借助嵌套查詢。 使用者變數賦值語法與流行的看法相反,使用者變數賦值可以直接整合到查詢中。 SET 語句的賦值運算子是= 或:=。但是,:= 必...
    程式設計 發佈於2024-11-06

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3